zoukankan      html  css  js  c++  java
  • 六、axios拦截器扩展3

    一、axios的请求与取消

    欢迎大家去验证:后台加个Thread.sleep(3000);,可以模拟网络延迟

    var vm=new Vue({
        el:"#div_id",
        data:{
            cancelTag:[],   //装所有的想要准备移除的请求,用处:当你离开这个页面时,将取消这个页面发出    的未完成的所有请求
            cancelCurrentTag:null,   //放置的是前一个单独的请求,用处:有时只想对某一个可能未完成的请求,让它取消
            
        },
        methods:{
            post:function(){  //post请求
                var CancelToken = axios.CancelToken;  //这里不写,下面new对象那里会报空
                axios({
                    headers: {
                          'Content-Type': 'application/json'
                    },
                    transformRequest: [function(data) {   //请求之前,对数据做处理
                          data = JSON.stringify(data)
                          return data
                    }],
                    timeout:5000,
                    url: '***',
                    method: 'post',
                    //params: {},
                    data: {
                          'code': 123,                      //传的参数
                          'data': "***"
                    },
                    // “cancelToken”指定可用于取消请求的取消令牌
                      cancelToken: new CancelToken(function (cancel) {
                          vm.cancelCurrentTag=cancel;
                          vm.cancelTag.push(cancel);  //动态放入
                      })
                }).then(function(res){   //想打出全部数据,可以使用console.log(JSON.stringify(err)),不会会显示object对象,而无法查看具体数据
                    console.log("请求数据:"+res.data)
                }).catch(function(err){
                    if(err!="Cancel"){  //非代码取消请求造成的异常,才输出显示
                        console.log("请求异常:"+err)
                    }
                })
            },
            cancelAll:function(){   //取消之前的全部请求
                $.each(this.cancelTag,function(i,item){
                    console.log("执行了")
                    item();
                })
                this.cancelTag=[];   //取消完之后,再清空记录
            },
            cancel:function(){
                console.log("执行")
                var j=-1;
                this.cancelCurrentTag();
                $.each(this.cancelTag,function(i,item){  //既然准备单独取消,就将总体中的该部分移去
                    if(item==vm.cancelCurrentTag)j=i;
                })
                if(j!=-1)this.cancelTag.splice(j,1);
            }
        }
    })

    二、在路由切换时取消axios请求demo

    <!DOCTYPE html >
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>在路由切换时取消axios请求demo</title>
        <!--    
        <script src="./库/vue.js"></script>
        <script src="./库/vue-router.js"></script> 
        <script src="./库/axios.js"></script> 
        -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script src="https://unpkg.com/vue-router@3.1.3/dist/vue-router.js"></script>
        <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    </head>
    
    <body>
        <div id="app">
            <router-link to="/home">home</router-link>
            <router-link to="/about">About</router-link>
            <hr>
            <router-view></router-view>
        </div>
    </body>
    <script>
    const Home = {
        template: `  
              <div>
                <h3>Home</h3>
                <button @click="sendRequest(false)">发送一个不能取消的请求</button>
              </div>
        `,
        methods: {
            sendRequest
        }
    }
    
    function sendRequest(whetherCancel) {
        axios.get("http://localhost:3000/demo", {
        //添加cancel数据,在拦截器中通过判断cancel添加CancleToken
            params: {
                cancel: whetherCancel
            }
        }).then(res => {
            if (res.data.status === 200) {
                console.log("请求成功")
            }
        }).catch(err => {
            axios.isCancel(err) ? console.log("请求取消了") : console.log(err)
        })
    }
    
    const About = {
        template: ` 
          <div>
            <h3>About</h3>
            <button @click="sendRequest(true)">发送一个能取消的请求</button>
          </div>
        `,
        methods: {
          sendRequest
        }
    }
    
    const routes = [{
        path: "/home",
        component: Home
    }, {
        path: "/about",
        component: About
    }]
    
    const CancelToken = axios.CancelToken;
    let cancel;
    
    const router = new VueRouter({
        routes
    })
    
    //拦截器
    axios.interceptors.request.use(config=> {
        //在拦截器中给每一个带有params.cancel为ture的请求的添加cancelToken
        if(config.params.cancel){
          config.cancelToken = new CancelToken(c => {
            cancel = c
          })
        }
        return config;
    }, (error)=> {
        // Do something with request error
        return Promise.reject(error);
    });
    
    
    //在路由守卫中通过source取消请求
    router.beforeEach((to, from, next) => {
        cancel && cancel()
        next()
    })
    
    new Vue({
        el: "#app",
        router
    })
    </script>
    
    </html>

     三、借用Windows对象

    在拦截器全局设置,用来取消所有请求:

    import axios from "axios";
     
    window.axiosCancel = []  // 全局定义一个存放取消请求的标识
    const Axios = axios.create({ 
        baseURL:"",
        timeout: 10000, 
        ...
    });
     
    //请求前拦截
    Axios.interceptors.request.use(config => {
        return config
        // 添加取消标记
        config.cancelToken = new axios.CancelToken(cancel => {
            window.axiosCancel.push({
            cancel
        })
     
    },function(error) {
        return Promise.reject(error)
    });
     
    //请求后返回数据拦截
    Axios.interceptors.response.use(res => {
            
    },function axiosRetryInterceptor(res) {
        return Promise.reject(res )
    });
    export default Axios

    然后在组件中使用,发送一个新的请求之前,取消前面的所有正在请求的请求,如下:

    methods:{
        cancel(){ // 设置一个函数,在执行请求前先执行这个函数
            // 获取缓存的 请求取消标识 数组,取消所有关联的请求
            let cancelArr = window.axiosCancel;
            cancelArr.forEach((ele, index) => {
                ele.cancel("取消了请求") // 在失败函数中返回这里自定义的错误信息
                delete window.axiosCancel[index]
            })
        },
        getList(){
            this.cancel()   // 取消所有正在发送请求的请求
            axios.post(..)  // 发送一个新的请求
        }
    }

    如果不希望每个组件里面都定义一个cancel函数,我们可以把这个函数挂载到vue实例的原型上,这样就可以在任何组件中使用cancel函数了:this.cancel(),如下main.js文件中:

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    import store from './store'//引入store
    Vue.config.productionTip = false
     
    // 将cancel,挂载到vue原型上
    Vue.prototype.cancel = function(){
        // 获取缓存的 请求取消标识 数组,取消所有关联的请求
        let cancelArr = window.axiosCancel;
        cancelArr.forEach((ele, index) => {
            ele.cancel("取消了请求")  // 在失败函数中返回这里自定义的错误信息
            delete window.axiosCancel[index]
        })
    }
     
    window.vm=new Vue({
      el: '#app',
      data(){
        return{
        }
      },
      router,
      store,
      components: { App },
    })

    另外如果想每次路由页面跳转时,取消上一个页面的所有请求,我们可以把cancel()函数的内容放在路由拦截器中,router/index.js文件配置,如下:

    // 引入路由以及vue,下面的是固定写法,照写就可以
    import Vue from 'vue'
    import Router from 'vue-router'
    Vue.use(Router)
     
    //创建路由实例
    const router = new Router({
      linkActiveClass: 'app-active', // 路由点击选中时的颜色(app-active为自定义的class样式类)
      routes: [
        { // 根路径
        path: '/',
        redirect: '/home',
        component: () => import('@/pages/home')  // 路由懒加载写法
        },
        {
        path: '/home',
        name: 'home',
        component: () => import('@/pages/home'),
        }
    })
     
    /* 路由拦截器 路由跳转前的操作 */
    router.beforeEach((to, from, next) => {
        // 获取缓存的 请求取消标识 数组,取消所有关联的请求
        let cancelArr = window.axiosCancel;
        cancelArr.forEach((ele, index) => {
            ele.cancel("取消了请求")  // 在失败函数中返回这里自定义的错误信息
            delete window.axiosCancel[index]
        })
        next()
    })
    /* 路由拦截器 路由跳转后的操作 */
    router.afterEach(to => {
     
    })
     
    // 将路由导出,供外部接收,主要用于main.js接收
    export default router

     四、借助全局对象

    main.js 

    Vue.Cancel = [] //全局定义一个对象
     
    router.beforeEach((to, from, next) => {
     
    while (Vue.Cancel.length > 0) { // 存储的对象进行abort()
     
    Vue.Cancel.shift().abort()
     
    }
     
    }

    请求的地方加上

     oneRequest = context.$http.post(url, newParams, //这里用的是vue-resource
                { // 发送请求前把request存放在Vue.Cancel对象中,为后面路由切换的时候中断使用
                  // use before callback
                  before (request) {
                    Vue.Cancel.push(request)
                  }
                }
              )
  • 相关阅读:
    UVa OJ 148 Anagram checker (回文构词检测)
    UVa OJ 134 LoglanA Logical Language (Loglan逻辑语言)
    平面内两条线段的位置关系(相交)判定与交点求解
    UVa OJ 130 Roman Roulette (罗马轮盘赌)
    UVa OJ 135 No Rectangles (没有矩形)
    混合函数继承方式构造函数
    html5基础(第一天)
    js中substr,substring,indexOf,lastIndexOf,split等的用法
    css的textindent属性实现段落第一行缩进
    普通的css普通的描边字
  • 原文地址:https://www.cnblogs.com/fger/p/12710018.html
Copyright © 2011-2022 走看看