05 Vue 最终

一. Promise

01 Promise介绍和基本使用

  • Promise是异步编程的一种解决方案
  • 什么时候会处理异步事务?
    一种很常见的场景就是网络请求,我们封装一个网络请求的函数,因为不能立即拿到结果,所以我们往往会传入另一个函数,在数据请求成功时,将数据通过传入的函数回调出去,如果只是简单的网络请求可以这样解决,但是当网络请求非常复杂时,就会出现回调地狱。
  1. 什么时候会用到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三种状态

  1. 当开发中有异步操作的时候,可以给异步操作包装一个Promise
  • 异步操作后会有三种状态
    • pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
    • fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
    • reject:决绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
  1. 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概念和作用解析

  1. Vuex是做什么的?
    在这里插入图片描述

  2. 管理什么状态?(需要在多个界面共享的状态)
    例如用户的登录状态,头像,名称或者商品的收藏、购物车里的物品等等。

02. 单界面到多界面状态管理切换

  1. 使用vuex之前需要先安装
    在安装的时候我出现了一个小bug:http自签名失败
    在这里插入图片描述
    按照网上的教程可以解决:
    在这里插入图片描述

  2. 使用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)
})
  1. 重新运行项目
    我们不需要使用以前父子组件传值的方法,直接$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

  1. vue-devtools的安装:教程分享
  2. 简单的使用案例:
  • 创建文件夹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
  1. 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)
    }
  },
  1. 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
 },
  1. 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')
}
  1. 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进行异步操作的。
  1. 虽然这样写看上去有点多余,但是却是必要的,这样我们的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('里面已经完成了');
        }
      })
    }
  1. 更优雅的写法:
    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
  1. 认识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')
    }
  1. 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没反应过来吧。

  1. 使用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的实例和模块封装

  1. 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:{}
})
  1. 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)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值