文章目录
一. Promise
01 Promise介绍和基本使用
- Promise是异步编程的一种解决方案
- 什么时候会处理异步事务?
一种很常见的场景就是网络请求,我们封装一个网络请求的函数,因为不能立即拿到结果,所以我们往往会传入另一个函数,在数据请求成功时,将数据通过传入的函数回调出去,如果只是简单的网络请求可以这样解决,但是当网络请求非常复杂时,就会出现回调地狱。
- 什么时候会用到Promise?
一般情况下是有异步操作时,使用Promise对这个异步操作进行封装
<script>
//new -> 构造函数(1.保存一些状态信息 2.执行传入的函数)
//在执行传入的回调函数时,会传入两个参数,resolve,reject,本身它们也是函数
new Promise((resolve,reject)=>{
setTimeout(()=>{
//01 成功的时候调用resolve
resolve('hello world') //会把data传给专门处理的函数
//02 失败的时候调用reject('error msg'),不会执行then
reject('error msg')
},1000)
}).then((data)=>{
//网络请求代码和处理代码做了分离
console.log(data);
console.log(data);
console.log(data);
console.log(data);
}).catch((err) => {
console.log(err);
})
</script>
02 Promise三种状态
- 当开发中有异步操作的时候,可以给异步操作包装一个Promise
- 异步操作后会有三种状态
- pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
- fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
- reject:决绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
- Promise的另外一种写法
<script>
new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve('hello vuejs')
reject('err msg')
},1000)
}).then(data=>{ //可以在then中同时定义满足的函数和拒绝的函数,省略catch()
console.log(data); //调用resolve时执行第一个方法
},err =>{
console.log(err); //调用reject时执行第二个方法
})
</script>
03 Promise的链式调用
*原始写法:
//01 ===== wrapped into ===========
//网络请求:aaa -> 自己处理(10行)
//处理:aaa111 -> 自己处理(10行)
//处理:aaa111222 -> 自己处理
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
//1 自己处理
console.log(res,'第一层的10行处理代码');
//2 对结果进行第一次处理
return new Promise((resolve,reject)=>{ //如果只有resolve,其实reject是可以不写的
// resolve(res+'111') //不需要异步请求,自己处理
reject('err')
})
}).then((res)=>{
console.log(res,'第二层的10行处理代码');
return new Promise((resolve)=>{
resolve(res+'222')
})
}).then((res)=>{
console.log(res,'第三层的10行处理代码');
}).catch(err => {
console.log(err);
})
- 简写 resolve
//02 ============ 其实只有第一次使用了异步操作,二三层只是普通操作,没必要new Promise ============
new Promise(resolve => resolve(结果)) 简写
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
//1 自己处理
console.log(res,'第一层的10行处理代码');
//2 对结果进行第一次处理
return Promise.resolve(res+'111')
}).then((res)=>{
console.log(res,'第二层的10行处理代码');
return Promise.resolve(res+'222')
}).then((res)=>{
console.log(res,'第三层的10行处理代码');
})
//03 ============= 省略Promise.resolve ===========
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
//1 自己处理
console.log(res,'第一层的10行处理代码');
//2 对结果进行第一次处理
return res+'111' //内部会进行包装,调用resolve
}).then((res)=>{
console.log(res,'第二层的10行处理代码');
return res+'222'
}).then((res)=>{
console.log(res,'第三层的10行处理代码');
})
- 简写 reject
//reject的简写:
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
//1 自己处理
console.log(res,'第一层的10行处理代码');
//2 对结果进行第一次处理
// return Promise.reject('err msg') //01 错误时:Promise.reject(结果)
throw 'error msg' //02 也可以手动抛出异常,也可以在catch拿到错误信息
}).then((res)=>{
console.log(res,'第二层的10行处理代码');
return Promise.resolve(res+'222')
}).then((res)=>{
console.log(res,'第三层的10行处理代码');
}).catch(err => {
console.log(err);
})
04 Promise的all方法使用
<script>
//某个需求需要发送两次网络请求才能完成
Promise.all([
//内部自动判断两个网络请求有没有都完成,都完成则去到then处理
// new Promise((resolve,reject)=>{
// $ajax({
// url:'url1',
// success:function(data){
// resolve(data) //有结果则回调resolve
// }
// })
// }),
// new Promise((resolve,reject)=>{
// $ajax({
// url:'url2',
// success:function(data){
// resolve(data)
// }
// })
// })
//模拟同时有两个异步请求
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve({name:'pao',age:18})
},2000)
}),
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve({name:'ko',age:19})
},1000)
})
]).then(results => { //results是一个数组,包含两个请求结果,统一进行处理
console.log(results); // ["result1", "result2"]
})
</script>
二. Vuex
01. Vuex概念和作用解析
-
Vuex是做什么的?
-
管理什么状态?(需要在多个界面共享的状态)
例如用户的登录状态,头像,名称或者商品的收藏、购物车里的物品等等。
02. 单界面到多界面状态管理切换
-
使用vuex之前需要先安装
在安装的时候我出现了一个小bug:http自签名失败
按照网上的教程可以解决:
-
使用vuex
创建文件夹store(仓库),新建index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
//1 安装插件
Vue.use(Vuex)
//2 创建对象
const store = new Vuex.Store({
state:{
count:1000
},
mutations:{
},
actions:{
},
getters:{
},
modules:{
}
})
//3 导出store对象
export default store
//main.js中导入
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
render: h => h(App)
})
- 重新运行项目
我们不需要使用以前父子组件传值的方法,直接$store.state.count就可以获取在state中保存的值。
<template>
<div>
<h2>{{$store.state.count}}</h2>
</div>
</template>
<script>
export default {
name:'HelloVuex',
// props:{
// count:Number
// }
}
</script>
- 这里报错:因为我刚才在cmd终端安装的vuex,vscode可能没有反应过来,所以再安装一遍,安装出错可以试试:npm报错
- 按教程清一下缓存再安装:成功!
- 这时就可以npm run dev运行项目了。
03. vue-devtools和mutations
- vue-devtools的安装:教程分享
- 简单的使用案例:
- 创建文件夹store,创建index.js文件,我们在state中定义了一个共享的变量count,在mutations中定义了两个方法来控制count的增减。
import Vue from 'vue'
import Vuex from 'vuex'
//1 安装插件
Vue.use(Vuex)
//2 创建对象
const store = new Vuex.Store({
state:{
count:1000
},
mutations:{
//方法
increment(state){
state.count++
},
decrement(state){
state.count--
}
},
actions:{
},
getters:{
},
modules:{
}
})
//3 导出store对象
export default store
- 让所有vue组件都可以使用这个store对象,我们需要在main.js中导入store对象,并且放在new Vue中,这样在其他组件里就可以通过this.$store的方式获取这个store对象了。
//main.js
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
render: h => h(App)
})
- 使用vuex的count
* 通过this.$store.state属性的方法来访问状态
* 通过this.$store.commit(‘mutation中的方法’)来修改状态 - 注意:我们是通过提交mutation的方式,而非直接改变this.$store.state.count,这样Vuex可以更加明确地追踪状态的改变,不要直接改变this.$store.state.count的值。
//App.vue
<template>
<div id="app">
<h2>---------App内容---------</h2>
<h2>{{$store.state.count}}</h2>
<button @click="addition">+</button>
<button @click="substraction">-</button>
<!-- <hello-vuex :count="count"></hello-vuex> -->
<h2>---------Hello Vuex内容--------</h2>
<hello-vuex/>
</div>
</template>
<script>
import HelloVuex from './components/HelloVuex'
export default {
name: 'App',
data() {
return {
message:'我是app组件',
// count:0
}
},
components: {
HelloVuex
},
methods: {
addition(){
this.$store.commit('increment') //传入mutation中定义的方法名字
},
substraction(){
this.$store.commit('decrement')
}
},
}
</script>
<style>
</style>
04. vue五个核心
1. state单一状态树(Single Source of Truth 单一数据源)
- 在开发中,如果状态信息是保存到多个store中的,那么之后的管理和维护等等都会变得比较困难,因此Vuex使用了单一状态树来管理应用层级的全部状态。
- 单一状态树能够让我们以最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便地管理和维护。
2. Getters
- Getters的基本使用
//store/index.js
const store = new Vuex.Store({
state:{
count:1000,
students:[
{id:110,name:'why',age:18},
{id:111,name:'coco',age:20},
{id:112,name:'lolo',age:21},
{id:113,name:'hsh',age:24},
]
},
mutations:{...},
actions:{},
//从store拿某个数据,这个数据需要经过某种变化之后再返回,我们都可以给它定义一个getters
getters:{ //当对属性的输出需要做一些处理时,可以使用getters,就像计算属性一样
powerCounter(state){
return state.count * state.count //获取平方
},
more20stu(state){
return state.students.filter(s => s.age>20)
}
},
modules:{}
})
//App.vue --- 需要经过处理展示的数据都可以在state中的getters变化后获取
<h2>---------App内容,演示getters相关信息---------</h2>
<!-- <h2>{{$store.state.count * $store.state.count}}</h2> -->
<h2>{{$store.getters.powerCounter}}</h2>
<!-- <h2>{{more20stu}}</h2> 使用自己的计算属性 -->
<h2>{{$store.getters.more20stu}}</h2>
不要直接在App.vue中定义计算属性来处理数据,因为这仅仅对App.vue一个页面有效。
// computed: {
// more20stu(){ //使用计算属性,拿到state中的students进行过滤,但是这样写,每一个界面都需要添加一样的计算属性代码
// return this.$store.state.students.filter(s=>{
// return s.age > 20 //可以直接省略{}和return
// })
// }
// },
- getters作为参数和传递参数
getters:{
...
//02 getters作为参数传入可以方便我们拿到getters中其他数据
more20stuLength(state,getters){
// return state.students.filter(s => s.age>20).length
return getters.more20stu.length
},
//03 getters传递参数
moreAgeStu(state){
return function(age){ //返回一个函数给别人调用
return state.students.filter(s => s.age>age)
}
// return age => {
// return state.students.filter(s => s.age>age)
// }
}
},
//App.vue
<!-- <h2>{{$store.getters.more20stu.length}}</h2> -->
<h2>{{$store.getters.more20stuLength}}</h2>
<!-- 当getters需要传参数,getter中的moreAgeStu本身是返回一个函数的-->
<h2>{{$store.getters.moreAgeStu(21)}}</h2>
3. mutations
- Vuex的store状态的更新唯一方式:提交Mutation
- Mutation主要包括两个部分:
字符串的事件类型(type)
一个回调函数(handler),该回调函数的第一个参数就是state
- mutations传递参数
在通过mutation更新数据的时候,有时候希望携带一些额外的参数,这些参数被称为mutation的载荷(Payload)
mutations:{
//方法
...
incrementCount(state,count){
state.count += count
},
addStudent(state,stu){
state.students.push(stu)
}
},
//app.vue
<button @click="addCount(5)">+5</button>
<button @click="addCount(10)">+10</button>
<button @click="addStudent">添加学生</button>
...
methods: {
...
addCount(count){
this.$store.commit('incrementCount',count) //提交的时候,携带参数提交过去
},
addStudent(){
const stu = {id:114,name:'ami',age:25} //参数较多时,可以搞成一个对象
this.$store.commit('addStudent',stu)
}
},
- mutations提交风格
- 上面通过commit提交是一种普通的方式,Vue还提供了另外一种风格,它是一个包含type属性的对象。
//App.vue
addCount(count){
//1 普通的提交风格
// this.$store.commit('incrementCount',count) //提交的时候,携带参数提交过去
//2 特殊的提交风格
this.$store.commit({
type:'incrementCount',
count:count
})
},
//index.js --- mutations
incrementCount(state,payload){ //当使用特殊的提交风格时,payload只是一个名称,代表我们commit的整个对象
// console.log(count); {type: "incrementCount", count: 10}
state.count += payload.count
},
- vuex响应式原理
state中定义的数据,它们的属性都会加入到响应式系统中,而响应式系统会监听属性的变化,当属性发生变化时,会通知所有界面中用到该属性的地方,让界面发生刷新。
- 我们必须遵守Vuex对应的规则:
- 提前在store中初始化好所需的属性
- 当给state中的对象添加新属性时,使用下面的方式:
方式一:使用Vue.set(obj,‘newProp’,1)
方式二:用新对象给旧对象重新赋值
updateInfo(state){
state.info.name='codewhy' //改变属性
//添加属性
// state.info['address'] = '洛杉矶' 非响应式
Vue.set(state.info,'address','洛杉矶') //将该属性也添加到响应式系统
//删除属性
// delete state.info.age 该方法也不是响应式
Vue.delete(state.info,'age')
}
- mutations的类型常量
在mutation中,我们定义了很多事件类型(也就是其中的方法名称),当方法越来越多的时候,我们在多个文件之间来回切换,可能会写错方法的名字,所以我们最好把方法的名字抽取成常量。
//mutations-types.js
我们可以把mutations中的方法类型全部在这里抽取成常量
export const INCREMENT = 'increment'
//mutations中我们直接这样定义方法
mutations:{
//方法
[INCREMENT](state){
state.count++
},
...
}
//App.vue
//在需要提交方法的地方,我们也以这个常量代替方法名
methods: {
addition(){
this.$store.commit(INCREMENT) //传入mutation中定义的方法名字
},
...
}
3. vuex-actions
- 通常情况下,Vuex要求我们Mutations中的方法必须是同步方法,主要原因是当我们使用devtools时,可以devtools可以帮助我们捕捉mutation的快照。但是如果是异步操作,那么devtools将不能很好地追踪这个操作什么时候会被完成。
- Action类似于Mutation,是用来代替mutation进行异步操作的。
- 虽然这样写看上去有点多余,但是却是必要的,这样我们的devtools就可以跟踪到修改了,并且在actions中也是可以传递参数或函数的。
mutations:{
...
updateInfo(state){
state.info.name='codewhy' //改变属性
//错误代码,不能在这里进行异步操作,devtools无法跟踪
// setTimeout(()=>{
// state.info.name='codewhy'
// },1000)
}
},
actions:{
//context上下文
aUpdateInfo(context,payload){ //payload接收参数
//异步操作
setTimeout(()=>{
// context.state.info.name = 'codewhy' 修改state只能在mutaions中,不要直接改!
context.commit('updateInfo')
console.log(payload); //打印传递过来的参数
},1000)
--------------------------------------
setTimeout(()=>{
context.commit('updateInfo')
payload() //提交后回调这个函数通知外面已经完成了
},1000)
--------------------------------------
setTimeout(()=>{
context.commit('updateInfo')
console.log(payload.message) //打印参数
payload.success() //回调函数
},1000)
}
},
//App.vue
updateInfo(){
// this.$store.commit('updateInfo') --- commit是提交到mutations
//异步操作需要经过actions
//01 传递参数
this.$store.dispatch('aUpdateInfo','我是传递来的参数')
--------------------------------------
//02 传递一个函数
this.$store.dispatch('aUpdateInfo',()=>{
console.log('里面已经完成了');
})
--------------------------------------
//03 既传递参数又传递函数
this.$store.dispatch('aUpdateInfo',{
message:'我是携带的信息',
success:()=>{
console.log('里面已经完成了');
}
})
}
- 更优雅的写法:
actions中方法本身可以返回一个Promise,我们可以在另一个地方dispatch拿到这个Promise,在后面写then方法,就可以继续使用这个Promise了。
//index.js
actions:{
aUpdateInfo(context,payload){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
context.commit('updateInfo')
console.log(payload); //打印传递的参数
resolve('1111111') //提交完毕后会执行这里的代码
},1000)
})
}
},
//App.vue
updateInfo(){
//使用dispatch,而aUpdateInfo定义了Promisse,所以返回的promise可以在这里用,内部可以告诉外部一些信息
this.$store.dispatch('aUpdateInfo','我是携带的信息').then(res=>{
console.log('里面已经完成了提交'); //提示
console.log(res);
})
}
4. vuex-modules
- 认识module(模块)
Vue使用单一状态树,那么意味着很多状态都会交给Vuex来管理,当应用变得非常复杂时,store对象就有可能变得相当臃肿,为了解决这个问题,Vuex允许我们将store分割成模块,而每个模块拥有自己的state、mutations、actions、getters等
- 用法和之前是差不多的:
//index.js
const moduleA = {
state:{
name:'lisa'
},
mutations:{
updatedName(state,payload) { //不要起重复的名字,否则提交可能会错误
state.name = payload
},
},
getters:{
fullname(state){
return state.name + '1111'
},
fullname2(state,getters){
return getters.fullname + '2222'
},
fullname3(state,getters,rootState){ //在模块中可以有第三个参数,拿到根的state
return getters.fullname2 + rootState.count
}
},
actions:{
aUpdateName(context){
setTimeout(()=>{
context.commit('updatedName','wangwu') //只commit自己的mutations
},1000)
}
},
}
const store = new Vuex.Store({
...
modules:{
a: moduleA //这个a会被放入state中
}
})
//App.vue
<h2>---------App内容,modules中的内容---------</h2>
//a是放在state中的
<h2>{{$store.state.a.name}}</h2>
//提交到mutation的方法
<button @click="updateName">修改名字</button>
//getters
<h2>{{$store.getters.fullname}}</h2>
<h2>{{$store.getters.fullname2}}</h2>
<h2>{{$store.getters.fullname3}}</h2>
//异步
<button @click="asyncUpdateName">异步修改名字</button>
...
updateName(){
this.$store.commit('updatedName','jenny') //直接commit,只要方法名不重复一般不会错
},
asyncUpdateName(){
this.$store.dispatch('aUpdateName')
}
- vue-store文件夹的目录结构
除了state(没必要)之外,其他各个核心的代码都可以单独抽出来,方便管理。
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
import moduleA from './modules/moduleA'
//1 安装插件
Vue.use(Vuex)
//2 创建对象
const state = { //数据都是响应式的
count:1000,
students:[
{id:110,name:'why',age:18},
{id:111,name:'coco',age:20},
{id:112,name:'lolo',age:21},
{id:113,name:'hsh',age:24},
],
info:{
name:'kobi',
age:40,
height:1.88
}
}
const store = new Vuex.Store({
state:state,
mutations:mutations,
actions:actions,
//从store拿某个数据,这个数据需要经过某种变化之后再返回,我们都可以给它定义一个getters
getters:getters,
modules:{
a: moduleA //这个a会被放入state中
}
})
//3 导出store对象
export default store
三. axios
01 axios框架的基本使用
1.安装axios框架
安装时出bug:代理有问题
找了一篇关于解决的博客:参考
还是不会安装,所以我尝试了另一个:cnpm
查了一下版本之后,居然就可以安装了,可能还是npm没反应过来吧。
- 使用axios
import Vue from 'vue'
import App from './App'
import axios from 'axios'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(App)
})
//axios支持Promise
axios({
url:'http://123.207.32.32:8000/home/multidata', //只传url默认是get请求
// method:'POST'
method:'GET' //指定请求方式,该接口暂时不支持post
}).then(res => {
console.log(res);
})
axios({
url:'http://123.207.32.32:8000/home/data', //可以直接跟参数?type=sell&page=3,或者下面单独写在params中
//专门针对get请求的参数拼接
params:{
type:'pop',
page:1
}
}).then(res => {
console.log(res);
})
02 axios发送并发请求
//使用全局的axios和对应的配置在进行网络请求
//2.axios发送并发请求 -- 对传入的多个网络请求进行合并
axios.all([
axios({
url:'http://123.207.32.32:8000/home/multidata',
}),
axios({
url:'http://123.207.32.32:8000/home/data',
params:{
type:'sell',
page:5
}
})
]).then(axios.spread((res1,res2) => {
//axios.add([])返回的结果是一个数组,使用axios.spread可将数组[res1,res2]展开为res1,res2
console.log(res1);
console.log(res2);
}))
// results => { //两个网络请求都完成后进行处理
// console.log(results);
// }
- 补充知识:
//对象的解构
const obj = {
name:'kobi',
age:30
}
const {name,age} = obj
//数组的解构
const names = ['why','are','you']
const [name1,name2,name3] = names
03 axios的配置信息相关
//3.axios的全局配置 -- 公共
axios.defaults.baseURL = 'http://123.207.32.32:8000'
axios.defaults.timeout = 5000 //设置超时
axios.all([
axios({
url:'/home/multidata', //只需要写不是公共部分的url
}),
axios({
url:'/home/data',
...
})
]).then(...)
04 axios的实例和模块封装
- axios的实例
当项目变得复杂,接口的服务器不一定只有一个,这时我们使用全局配置的baseURL不满足需求,所以我们一般不会直接使用全局,而是创建一个实例,而且实例一般会有多个。
//创建对应的axios的实例
const instance1 = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
})
//使用实例
instance1({
url:'/home/multidata'
}).then(res => {
console.log(res);
})
instance1({
url:'/home/data',
params:{
type:'pop',
page:1
}
}).then(res => {
console.log(res);
})
//每个实例有自己独立的配置
const instance2 = axios.create({
baseURL:'http://111.222.32.32:8000',
timeout:10000,
headers:{}
})
- axios的模块封装
在使用第三方框架的时候,最好不要每个地方都引用,而是对它做一个封装,否则以后如果这个框架废弃或者出现问题时,更换框架会变得困难。
- 第一种封装:
//----------- network/request.js -----------
//对axios做封装
import axios from 'axios'
//1.传入配置以及两个回调函数
export function request(config,success,failure){
//1 创建axios实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
})
//发送真正的网络请求
instance(config)
.then(res => {
// console.log(res);
success(res); //回调出去
})
.catch(err => {
// console.log(err);
failure(err);
})
}
//----------- mian.js -----------
//5.封装一个request模块
import {request} from './network/request';
request({
url:'/home/multidata'
},res => {
console.log(res);
},err => {
console.log(err);
})
- 第二种封装:但是这种也不是最终方案
//request.js
//只传入一个参数,但是要求参数里必须传入回调函数
export function request(config){
//1 创建axios实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
})
//发送真正的网络请求
instance(config.baseConfig)
.then(res => {
config.success(res); //回调出去
})
.catch(err => {
config.failure(err);
})
}
//main.js
//把所有东西放到大的config中
request({
baseConfig:{
},
success:function(){
},
faliure:function(){
}
})
- 第三种封装:使用Promise
//request.js
export function request(config){
return new Promise((resolve,reject) => {
//1 创建axios实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
})
//发送真正的网络请求 --- 这里进行异步操作
instance(config)
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
-------------最终:简化后-----------------------
export function request(config){
const instance = axios.create({ //实例
baseURL:'http://123.207.32.32:8000',
timeout:5000
})
//直接返回,instance本身就返回一个Promise --- 看源码
return instance(config)
}
// ------- main.js -------
//3. 继续调用Promise
request({
url:'/home/multidata'
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
05 axios拦截器的使用
- axios提供了拦截器,用于我们在发送每次请求或得到响应后,进行对应的处理。
- 拦截请求或者响应之后还需要返回,否则信息被拦截,请求方获取不到。
export function request(config){
const instance = axios.create({ //实例
baseURL:'http://123.207.32.32:8000',
timeout:5000
})
//2.axios的拦截器
// axios.interceptors 拦截全局
instance.interceptors.request.use(config => { //拦截请求
console.log(config);
//2.1请求拦截的作用:
//01 比如config中的一些信息不符合服务器的要求
//02 比如每次发送网络请求时,都希望在界面中显示一个显示的图标
//03 某些网络请求(比如登录token),必须携带一些特殊的信息
return config; //还得返回,否则config被拦截
},err => {
console.log(err);
});
instance.interceptors.response.use(res => { //拦截响应
// console.log(res);
// res.data 过滤有用的信息
return res.data //处理完结果必须返回,否则请求拿不到结果
},err => {
console.log(err); //Error: Request failed
});
//直接返回,instance本身就返回一个Promise --- 看源码
return instance(config)
}