美文网首页基础前端
学习 axios 的基本使用和项目级封装

学习 axios 的基本使用和项目级封装

作者: CondorHero | 来源:发表于2019-09-25 18:52 被阅读0次

    一、Ajax

    在很久以前项目中进行数据处理通常是发送 Ajax(Asynchronous JavaScript and XML),以前使用原生的 XMLHTTPRequest。

    其中传统的 Web 应用允许用户端填写表单(form),当提交表单时就向网页服务器发送一个请求。服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中的大部分HTML码往往是相同的。最重要的是网页会跳转,页面的重新刷新。

    XMLHttpRequest 是一个API,微软发明,但是早期一直没有标准化,每家浏览器的实现或多或少有点不同。2008年2月,就提出了XMLHttpRequest Level 2 草案。

    它请求数据不会使整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。而且 XMLHttpRequest 可以取回所有类型的数据资源,并不局限于XML。 而且除了HTTP ,它还支持fileftp 协议。

    老的模板如下:

    var xhr = new XMLHttpRequest(); // 创建xhr对象
    xhr.open( method, url ,true);
    xhr.onreadystatechange = function () { ... };
    xhr.setRequestHeader( ..., ... );
    xhr.send( optionalEncodedData );
    

    新的模板如下

     let xhr = new XMLHttpRequest();
    // 请求成功回调函数
    xhr.onload = e => {
        console.log('request success');
    };
    // 请求结束
    xhr.onloadend = e => {
        console.log('request loadend');
    };
    // 请求出错
    xhr.onerror = e => {
        console.log('request error');
    };
    // 请求超时
    xhr.ontimeout = e => {
        console.log('request timeout');
    };
    //进度信息,分成上传和下载两种情况。下载的progress事件属于XMLHttpRequest对象,上传的progress事件属于XMLHttpRequest.upload对象。
    xhr.onprogress = updateProgress;
    xhr.upload.onprogress = updateProgress;
    function updateProgress(event) {
        if (event.lengthComputable) {
            //lengthComputable:返回一个布尔值,表示当前进度是否具有可计算的长度。如果为false,event.total=0。
            let percentComplete = event.loaded / event.total; 
            //event.total是需要传输的总字节,event.loaded是已经传输的字节。
        } 
    }
    与progress事件相关的,还有其他五个事件,可以分别指定回调函数:
    
      * load事件:传输成功完成。
    
      * abort事件:传输被用户取消。
    
      * error事件:传输中出现错误。
    
      * loadstart事件:传输开始。
    
      * loadEnd事件:传输结束,但是不知道成功还是失败。
    // 请求回调函数.XMLHttpRequest标准又分为Level 1和Level 2,这是Level 1和的回调处理方式
    // xhr.onreadystatechange = () => {
    //  if (xhr.readyState !== 4) {
    //  return;
    //  }
    //  const status = xhr.status;
    //  if ((status >= 200 && status < 300) || status === 304) {
    //  console.log(xhr.responseText);
    //  } else {
    //  console.log(xhr.statusText);
    //  }
    //  };
    
    xhr.timeout = 0; // 设置超时时间,0表示永不超时
    // 初始化请求
    xhr.open('GET/POST/DELETE/...', '/url', true || false);
    // 设置期望的返回数据类型 'json' 'text' 'document' ...
    xhr.responseType = '';
    // 设置请求头
    xhr.setRequestHeader('', '');
    // 发送请求
    xhr.send(null || new FormData || 'a=1&b=2' || 'json字符串');
    

    http2 去参考
    阮一峰 - XMLHttpRequest Level 2 使用指南
    你不知道的 XMLHttpRequest

    Jquery的Ajax

    这个就很熟了吧,放个模板:

    $.ajax({
       type: 'POST',
       url: url,
       data: data,
       dataType: dataType,
       success: function () {},
       error: function () {}
    });
    

    JQuery 对其 XMLHTTPRequest 进行了封装,还增添了对 JSONP 的支持。

    ES6 的fetch

    fetch是基于Promise设计的号称是 AJAX 的替代品,它的好处在《传统 Ajax 已死,Fetch 永生》中提到的有:

    语法简单,更加语义化
    基于标准的Promise实现,支持async/await
    脱离了XHR,是ES规范里新的实现方式
    但是 fetch 缺点也很明显:

    1. fetch只对网络请求报错,没有状态码,需要自己封装
    2. fetch默认不会带cookie,需要添加配置项
    3. fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费
    4. fetch没有办法原生监测请求的进度,而XHR可以
    5. fetch不支持超时timeout处理
    6. fetch不支持JSONP

    深入可参考:《fetch没有你想象的那么美》《fetch使用的常见问题及解决方法

    现在的王者 axios

    fetch 太新还需要完善,JQuery 已经迟暮,现在的王者当然属于 axios 了。axios 作为 Ajax 的替代品,底层是原生的 Ajax,没有使用 fetch,但是封装的和内置fetch 一样好用。它有很多优秀的特性,例如拦截请求和响应、取消请求、转换json、客户端防御XSRF等。所以我们的尤大大也是果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库。如果还对axios不了解的,可以移步axios文档

    一、axios 一些配置
    • 全局默认配置
      当我们使用 axios 的时候,可以使用以下代码进行 axios 默认配置。
    import axios from "axios";
    axios.defaults.baseURL = 'http://127.0.0.1:8080/api/';//每条axios请求都会加上这个基准网址
    axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
    
    • 实例化配置
    import axios from "axios";
    
    const http = axios.create({
        baseURL : 'http://127.0.0.1:8080/api/',
        timeout : 1000 
    });
    
    export default http;
    

    实例化配置详解axios.create({})里面的配置对象提取出来为 config:

    import axios from "axios";
    const config = {
        // `url` 是用于请求的服务器 URL
        //如axios.get(url,config);这里的url会覆盖掉config中的url
        url: '/',
    
        // `method` 是请求时的方法
        method: 'get', // 默认是 get
    
        // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
        baseURL: 'api/',
    
        // `transformRequest` 允许在向服务器发送前,修改请求数据,即要传递的data数据
        // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
        // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
        transformRequest: [function (data) {
            // 对 data 进行任意转换处理
            data = JSON.stringify(data);
            //当我们发送POST请求的时候,如果打开这个函数,后台会得到的结果[Object,Object]
            //要么不打开要么变成字符串
            return data;
        }],
    
        // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
        //不分请求方式
        transformResponse: [function (data) {
            // 对 data 进行任意转换处理
            return data;
        }],
    
        // `headers` 是即将被发送的自定义请求头
        //NodeJs通过req.headers['x-requested-with']能得到XMLHttpRequest
        //用来判断是同步提交还是异步提交
        //"content-Type":"application/x-www-form-urlencoded"请求头
        headers: {
            'X-Requested-With': 'XMLHttpRequest',
            //'Content-Type': 'application/x-www-form-urlencoded',
            //'Token': '',
            'Access-Control-Allow-Origin': '*',
            'Content-Type': 'application/json',
        },
    
        // `params` 是即将与请求一起发送的 URL 参数
        // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
        params: {
    
        },
    
        //没明白这个配置
        // `paramsSerializer` 是一个负责 `params` 序列化的函数
        // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
        // paramsSerializer: function(params) {
        //  // return Qs.stringify(params, {arrayFormat: 'brackets'})
        // },
    
        // `data` 是作为请求主体被发送的数据
        // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
        // 在没有设置 `transformRequest` 时,必须是以下类型之一:
        // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
        // - 浏览器专属:FormData, File, Blob
        // - Node 专属: Stream
        data: {
    
        },
    
        // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
        // 如果请求响应时间超过 `timeout` 的时间,请求将被中断
        timeout: 3000,
    
        // `withCredentials` 表示跨域是否携带cookie,三步设置才能生效
        withCredentials: false, // 默认的
    
        //没明白
        // `adapter` 允许自定义处理请求,以使测试更轻松
        // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
        // adapter: function (config) {
        //   /* ... */
        // },
    
        // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
        // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
        //NodeJs 通过req.headers.authorization可以得到
        //这个和token登录不一样
        auth: {
            username: 'Condor Hero',
            password: 'password'
        },
    
        // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
        responseType: 'json', // 默认的
    
        // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
        // xsrfCookieName: 'XSRF-TOKEN', // default
    
        // `xsrfHeaderName` 是承载 xsrf token 的值的 HTTP 头的名称
        // xsrfHeaderName: 'X-XSRF-TOKEN', // 默认的
    
        // `onUploadProgress` 允许为上传处理进度事件
        // onUploadProgress: function (progressEvent) {
        //   // 对原生进度事件的处理
        // },
    
        // `onDownloadProgress` 允许为下载处理进度事件
        // onDownloadProgress: function (progressEvent) {
        //   // 对原生进度事件的处理
        // },
    
        // `maxContentLength` 定义允许的响应内容的最大尺寸
        // maxContentLength: 2000,
    
        // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
        // validateStatus: function (status) {
        //   return status >= 200 && status < 300; // 默认的
        // },
    
        // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
        // 如果设置为0,将不会 follow 任何重定向
        maxRedirects: 5, // 默认的
    
      // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
      // `keepAlive` 默认没有启用
      // httpAgent: new http.Agent({ keepAlive: true }),
      // httpsAgent: new https.Agent({ keepAlive: true }),
    
      // 'proxy' 定义代理服务器的主机名称和端口
      // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
      // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
      // proxy: {
      //   host: '127.0.0.1',
      //   port: 9000,
      //   auth: {
      //     username: 'mikeymike',
      //     password: 'rapunz3l'
      //   }
      // },
    
      // `cancelToken` 指定用于取消请求的 cancel token
      // (查看后面的 Cancellation 这节了解更多)
      // cancelToken: new CancelToken(function (cancel) {})
    }
    
    
    
    // 创建实例时设置配置的默认值
    const http = axios.create(config);
    
    // 添加请求拦截器
    http.interceptors.request.use(config => {
        // 在发送请求之前做些什么
        return config;
    }, function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
    });
    
    // 添加响应拦截器data.data
    http.interceptors.response.use(function (response) {
        // 对响应数据做点什么response.status
        return response;
    }, function (error) {
        // 对响应错误做点什么error.response.status
        return Promise.reject(error);
    });
    
    
    export default http;
    

    注释掉的都是不太懂的,除了上传下载。。。
    几点说明:

    1. 请求头 content-type 不写默认使用 json ,请求的格式 payload ,也可以定义为下面的这种格式。
    headers: {'X-Requested-With': 'XMLHttpRequest',"content-Type":"application/x-www-form-urlencoded"},
    
    content-type:application/json
    content-Type":"application/x-www-form-urlencoded
    1. 某个请求的响应包含以下信息:
    {
      // `data` 由服务器提供的响应
      data: {},
    
      // `status` 来自服务器响应的 HTTP 状态码
      status: 200,
    
      // `statusText` 来自服务器响应的 HTTP 状态信息
      statusText: 'OK',
    
      // `headers` 服务器响应的头
      headers: {},
    
       // `config` 是为请求提供的配置信息
      config: {},
     // 'request'
      // `request` is the request that generated this response
    // It is the last ClientRequest instance in node.js (in redirects)
      // and an XMLHttpRequest instance the browser
      request: {}
    }
    
    图证
    1. 并行请求
    const getUserAccount = ()=>{
        return axios.get("/list");
    }
    
    const getUserPermissions =  ()=> {
        return axios.post("post",{name:"Condor Hero"});
    }
    axios.all([getUserAccount(),getUserPermissions()]).then(axios.spread(function (acct, perms) {
        // 两个请求现在都执行完成
        console.log(acct,perms)
    }));
    
    • 自定义配置
    axios.get(url,{
        timeout: 5000
    })
    

    如果同时在三个配置设置里面 timeout 那他们的优先级如下:

    默认 < 实例 < 自定义

    二、拦截器 Interceptors

    在每次发请求之前,都会执行的函数,就是 axios 拦截器。通常用途:

    • 判断是否登录。
    • 制作 loading 动画、当超时、错误的时候集中处理错误样式。
    • 结合接口清单,判断接口是模拟还是真实。

    示例模板:

    import axios from "axios";
    
    const http = axios.create({
        baseURL : 'http://127.0.0.1:8080/api/',
        timeout : 1000 
    });
    // Add a request interceptor每次请求之前会经过这里
    axios.interceptors.request.use(function (config) {
        // Do something before request is sent
        // ①这里可以发送Ajax
        return config;
      }, function (error) {
        // Do something with request error
        return Promise.reject(error);
      });
     
    // Add a response interceptor每次请求响应之后会经过这里
    axios.interceptors.response.use(function (response) {
        // Do something with response data
        // 这里可根据①请求返回的结果进行权限判定非法登录等操作
        return response;
      }, function (error) {
        // Do something with response error
        //响应错误可在此操作返回模拟数据接口
        return Promise.reject(error);
      });
    export default http;
    
    三、封装 axios 1.0 版本

    一般我们封装的 Ajax 都会单独放在一个文件,常见的叫法就是 http ,API,Ajax,server,request等等。

    auth.js 这个文件是用来处理 token 的。关于 token 存储地方一般来讲我们是存储到 sessionStorage 里面,如果前端登录功能要做一个记住密码的功能,那我们能选择的就是存储到 localStorage 里面或者是存在 cookie 里面。cookie 默认是临时存储的,当浏览器关闭进程的时候自动销毁,每个不能超过 4KB,要想长时间保存一个cookie,就需要设置cookie的过期时间。

    关于登录时是使用 token 还是 cookie 进行身份验证,如果使用 token ,token 是放在 URL 里面还是请求头 head 里面,请看:

    Session与Token认证机制 前后端分离下如何登录

    下面是 cookie 最常见的应用场景了

    保存用户登录信息。这应该是最常用的了。当您访问一个需要登录的界面,例如微博、百度及一些论坛,在登录过后一般都会有类似"下次自动登录"的选项,勾选过后下次就不需要重复验证。这种就可以通过cookie保存用户的id。
    创建购物车。购物网站通常把已选物品保存在cookie中,这样可以实现不同页面之间数据的同步(同一个域名下是可以共享cookie的),同时在提交订单的时候又会把这些cookie传到后台。
    跟踪用户行为。例如百度联盟会通过cookie记录用户的偏好信息,然后向用户推荐个性化推广信息,所以浏览其他网页的时候经常会发现旁边的小广告都是自己最近百度搜过的东西。这是可以禁用的,这也是cookie的缺点之一。

    在 cookie 里写入、读取、删除,使用的是 js-cookie,下载量还是不少滴:


    2019年12月7日22:00:10

    使用方法也是很简单的,cookie 的 读、写、删。

    import Cookies from 'js-cookie'
    
    const TokenKey = 'X_Token'
    
    export function getToken() {
      return Cookies.get(TokenKey)
    }
    
    export function setToken(token) {
      return Cookies.set(TokenKey, token)
    }
    
    export function removeToken() {
      return Cookies.remove(TokenKey)
    }
    
    

    js-cookie 的原理就是使用 document.cookie 这个 API,详细原码去参考 js-cookie源码学习,我是不同意用 js-cookie 去存储token的,因为每次http请求都会携带cookie里面的数据,最好使用 HTML5 中的 sessionStorage 或 localStorage。但是如果项目浏览器不支持 H5 那 token 就只能存储在 cookie 里面了。

    request.js 的内容:

    import axios from 'axios';
    import {
      MessageBox,
      Message
    } from 'element-ui'
    import store from '@/store'
    import {
      getToken,
      removeToken
    } from '@/utils/auth'
    
    // create an axios instance
    const service = axios.create({
      baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
      withCredentials: true, // send cookies when cross-domain requests
      timeout: 50000 // request timeout
    })
    
    // request interceptor
    service.interceptors.request.use(
      config => {
        // do something before request is sent
        if (store.getters.token) {
          // let each request carry token
          // ['X-Token'] is a custom headers key
          config.headers['X-Token'] = getToken()
        }
        // 设置请求时间,为登录超时
        localStorage.setItem('lastRequestTime', new Date().getTime());
        return config
      },
      error => {
        // do something with request error
        // for debug
        return Promise.reject(error)
      }
    )
    
    // response interceptor
    service.interceptors.response.use(
      res => {
        if (res.status == 200) {
          if(res.data.status == 401) {
            // 清空token
            removeToken();
            // to re-login
            MessageBox.confirm('登录超时,您可以选择留在本页面或者重新登录', '登录超时', {
              confirmButtonText: '重新登录',
              cancelButtonText: '留在本页',
              type: 'warning'
            }).then(() => {
              store.dispatch('user/resetToken').then(() => {
                location.reload() // 为了重新实例化vue-router对象 避免bug
              })
            });
            return Promise.reject({message: '登陆超时'});
          } else {
            return res;
          }
        } else {
          Message({
            message: '网络异常', // error.message
            type: 'error',
            duration: 5 * 1000
          })
          return Promise.reject(error)
        }
      },
      error => {
        Message({
          message: '请求服务异常', // error.message
          type: 'error',
          duration: 5 * 1000
        })
        return Promise.reject(error)
      }
    )
    
    export default service
    

    上面 axios 实例化的时候有一个字段为:withCredentials:true 这表示什么来?

    // withCredentials indicates whether or not cross-site Access-Control requests
    // should be made using credentials
    withCredentials: false, // default

    官网介绍是跨域请求应该使用的凭证,翻译过来就是跨域带上cookies。同时后台需要配合设置 Access-Control-Allow-Origin 为你的源地址,例如 http://localhost:8080,而不能是 *,且还要设置 header('Access-Control-Allow-Credentials: true');

    上面 axios 是实例化直接暴露出来的,都没有对它的方法 get,put等进行封装,可能很多人会按如下的代码进行 axios 方法的封装:

    export function get(url, params = {}){    
        return new Promise((resolve, reject) =>{        
            axios.get(url, {            
                params: params        
            })        
            .then(res => {            
                resolve(res.data);        
            })        
            .catch(err => {            
                reject(err.data)        
            })    
        });
    }
    

    这样写的好处之一就是可以在全局直接引入

    import Vue from 'vue'
    import { post, get, patch, put, del } from './index'
    Vue.prototype.$post = post
    

    而不用每次在组件内部都引入。但是直接暴露 axios 的好处自定义化更高。看个人习惯这点。

    API 管理我们也会单独放在一个文件里面,例如涉及用户登录注册的这块全部放在 user.js 文件里面:

    import request from '@/utils/request'
    
    export function login(data) {
      return request({
        url: '/m/crops/admin/sys/login',
        method: 'post',
        data
      })
    }
    
    export function logout(data) {
      return request({
        url: '/m/crops/admin/sys/logout',
        method: 'post',
        data: data
      })
    }
    export function changePassword(data) {
      return request({
        url: '/m/crops/admin/sys/login',
        method: 'post',
        data
      })
    }
    
    export function changeInformation(data) {
      return request({
        url: '/m/crops/admin/sys/user/updateSysUserPassword',
        method: 'post',
        data: data
      })
    }
    
    export function updateSysUser(data) {
      return request({
        url: '/m/crops/admin/sys/user/updatePictureAndRealName',
        method: 'post',
        data: data
      })
    }
    
    

    当我们需要使用的时候只需要:

    import {
        addServiceStation
    } from "@/api/mapOn/index.js";
    addServiceStation(this.addForm).then(res => {
        if (res.data.status === 200) {
            this.$Notice.success({
                title: "更新成功",
                desc: ""
            });
            this.$router.push({
                name: "stationmanagement"
            });
        } else {
            this.$Notice.warning({
                title: "数据有误",
                desc: res.data.message
            });
        }
    });
    
    登录过期
    mounted() {
        let self = this;
        let loginTimeOut = self.$store.state.settings.loginTimeOut;//12 * 60 *1000
        let lastTime = localStorage.getItem('lastRequestTime');
        let currentTime;
        let interval;
    
        function checkTimeout() {
            currentTime = new Date().getTime();
            if (currentTime - lastTime  > loginTimeOut && getToken()) {
                // 清理定时器
                clearInterval(interval);
                // 清理token
                removeToken();
                self.$alert('您的登录信息已过期,请重新登录...', '登录超时', {
                    confirmButtonText: '重新登录',
                    type: 'warning'
                }).then(() => {
                    self.$store.dispatch('user/resetToken').then(() => {
                        location.reload() // 为了重新实例化vue-router对象 避免bug
                    })
                });
            }
        }
    
        interval = window.setInterval(checkTimeout, 1000);
    }
    

    另外一种方法去参考:vue中Axios的封装和API接口的管理
    文章作者最后修改的版本挺适合大型项目多人开发:
    base.js 文件:定义 baseURL

    /**
     * 接口域名的管理
     */
    const base = {    
        sq: 'https://xxxx111111.com/api/v1',    
        bd: 'http://xxxxx22222.com/api'
    }
    
    export default base;
    

    article.js:每个人负责的模块,例如你负责article模块

    /**
     * article模块接口列表
     */
    
    import base from './base'; // 导入接口域名列表
    import axios from '@/utils/http'; // 导入http中创建的axios实例
    import qs from 'qs'; // 根据需求是否导入qs模块
    
    const article = {    
        // 新闻列表    
        articleList () {        
            return axios.get(`${base.sq}/topics`);    
        },    
        // 新闻详情,演示    
        articleDetail (id, params) {        
            return axios.get(`${base.sq}/topic/${id}`, {            
                params: params        
            });    
        },
        // post提交    
        login (params) {        
            return axios.post(`${base.sq}/accesstoken`, qs.stringify(params));    
        }
        // 其他接口…………
    }
    
    export default article;
    

    api.js :把所有的模块进行合并整理

    /** 
     * api接口的统一出口
     */
    // 文章模块接口
    import article from '@/api/article';
    // 其他模块的接口……
    
    // 导出接口
    export default {    
        article,
        // ……
    }
    

    最后,为了方便内部组件的调用,我们需要将其挂载到 vue 的原型上。在main.js中:

    import Vue from 'vue'
    import App from './App'
    import router from './router' // 导入路由文件
    import store from './store' // 导入vuex文件
    import api from './api' // 导入api接口
    
    Vue.prototype.$api = api; // 将api挂载到vue的原型上
    

    然后我们可以在页面中这样调用接口,eg:

    methods: {    
        onLoad(id) {      
            this.$api.article.articleDetail(id, {        
                api: 123      
            }).then(res=> {
                // 执行某些操作      
            })    
        }  
    }
    

    最后还值得借鉴的是对状态码错误的处理,常见错误更加详细的告诉用户:

    // 状态码判断
    switch (status) {
        // 401: 未登录状态,跳转登录页
        case 401:
            toLogin();
            break;
        // 403 token过期
        // 清除token并跳转登录页
        case 403:
            tip('登录过期,请重新登录');
            localStorage.removeItem('token');
            store.commit('loginSuccess', null);
            setTimeout(() => {
                toLogin();
            }, 1000);
            break;
        // 404请求不存在
        case 404:
            tip('请求的资源不存在'); 
            break;
        default:
            console.log(other);   
    }
    

    相关文章

      网友评论

        本文标题:学习 axios 的基本使用和项目级封装

        本文链接:https://www.haomeiwen.com/subject/gevcuctx.html