Axios是近年来备受推崇的一个网络请求库,它以基于Promise的方式封装了浏览器的XMLHttpRequest和服务器端node http请求,使得咱们能够用es6推荐的异步方式处理网络请求。
功能特性:前端
axios.interceptors
拦截器主要用来做什么?和路由拦截有什么区别
axios拦截器分为请求拦截器和响应拦截器。用户能够经过then方法为请求添加回调,而拦截器中的回调将在then中的回调以前执行vue
// 添加请求拦截器 axios.interceptors.request.use(function (config) { // Do something before request is sent return config; }, function (error) { // Do something with request error return Promise.reject(error); }); // 添加响应拦截器 axios.interceptors.response.use(function (response) { // Do something with response data return response; }, function (error) { // Do something with response error return Promise.reject(error); });
移除已经设置的拦截器node
var myInterceptor = axios.interceptors.request.use(function () {/*...*/}); axios.interceptors.request.eject(myInterceptor);
给自定义的axios实例添加拦截器ios
var instance = axios.create(); instance.interceptors.request.use(function () {/*...*/});
import axios from 'axios' import env from '@/env' import Utils from '@/components/Utils' import { Message } from 'element-ui' // 获取系统ID const systemId = Utils.getQueryString('systemId') if (systemId) { window.systemId = systemId } else { // 没有系统ID location.href = env.dataCloud } const auth = (response) => { // 未登陆 if (response && ((response.status === 401) || (response.status === 412))) { location.href = env.dataCloud } } const instance = axios.create({ baseURL: `${env.api}${env.prefix.develop}`, params: { systemId }, withCredentials: true }) instance.nterceptors.response.use((response) => { auth(response) if (response && response.data && response.data.statusCode !== '0') { Message.error((response.data && response.data.msg) || response.data.errmsg || '抱歉') return Promise.reject(response).catch(() => { }) } return Promise.resolve(response.data) }, (error) => { let msg = '网络错误,请稍后再试' if (error && error.response && error.response.status === 401) { msg = '请登陆' } const notice = document.getElementsByClassName('ivu-message-error') if (notice.length === 0) { Message.error(msg) } auth(error && error.response) return Promise.reject(error).catch(() => { }) }) export default instance
login.js
git
main.js
es6
axios/lib/core/Axios.js
axios/lib/core/InterceptorManager.jsgithub
拦截器上有request,response。分别用于拦截发送,接收。vuex
好比这样一个场景:element-ui
在进行敏感操做(常见敏感操做如购买
,获取列表
等)以前,每一个请求须要携带token,可是token 有有效期,token 失效后须要换取新的token并继续请求。
需求分析:axios
每一个请求都须要携带 token ,因此咱们可使用 axios request 拦截器,在这里,咱们给每一个请求都加 token,这样就能够节省每一个请求再一次次的复制粘贴代码。
token 失效问题,当咱们token 失效,咱们服务端会返回一个特定的错误表示,好比 token invalid,可是咱们不能在每一个请求以后去作刷新 token 的操做呀,因此这里咱们就用 axios response 拦截器,咱们统一处理全部请求成功以后响应过来的数据,而后对特殊数据进行处理,其余的正常分发。
功能实现
在 main.js 注册 axios
jsVue.use(Vuex) Vue.use(VueAxios, axios) Vue.use(qs) 注:qs,使用axios,必须得安装 qs,全部的Post 请求,咱们都须要 qs,对参数进行序列化。 在 request 拦截器实现 axios.interceptors.request.use( config => { config.baseURL = '/api/' config.withCredentials = true // 容许携带token ,这个是解决跨域产生的相关问题 config.timeout = 6000 let token = sessionStorage.getItem('access_token') let csrf = store.getters.csrf if (token) { config.headers = { 'access-token': token, 'Content-Type': 'application/x-www-form-urlencoded' } } if (config.url === 'refresh') { config.headers = { 'refresh-token': sessionStorage.getItem('refresh_token'), 'Content-Type': 'application/x-www-form-urlencoded' } } return config }, error => { return Promise.reject(error) } ) //在 response 拦截器实现 axios.interceptors.response.use( response => { // 定时刷新access-token if (!response.data.value && response.data.data.message === 'token invalid') { // 刷新token store.dispatch('refresh').then(response => { sessionStorage.setItem('access_token', response.data) }).catch(error => { throw new Error('token刷新' + error) }) } return response }, error => { return Promise.reject(error) } )
[libcoreInterceptorManager.js L5]()
'use strict'; var utils = require('./../utils'); function InterceptorManager() { this.handlers = []; } /** * Add a new interceptor to the stack * * @param {Function} fulfilled The function to handle `then` for a `Promise` * @param {Function} rejected The function to handle `reject` for a `Promise` * * @return {Number} An ID used to remove interceptor later */ // InterceptorManager的对象中是经过handlers数组变量存储拦截器, // 数组每项同时包含了分别做为Promise中resolve和reject的回调。 // InterceptorManager类中还包含了对该数组变量的添加、 移除、 遍历方法。 InterceptorManager.prototype.use = function use(fulfilled, rejected) { this.handlers.push({ fulfilled: fulfilled, rejected: rejected }); return this.handlers.length - 1; }; /** * Remove an interceptor from the stack * * @param {Number} id The ID that was returned by `use` */ // 移除方法是经过直接将该项设为null实现的, // 而不是用splice剪切该数组, 遍历方法中也增长了相应的null值处理。 // 这样作一方面使得每一项ID保持为项的数组索引不变, // 另外一方面也避免了从新剪切拼接数组的性能损失。 InterceptorManager.prototype.eject = function eject(id) { if (this.handlers[id]) { this.handlers[id] = null; } }; /** * Iterate over all the registered interceptors * * This method is particularly useful for skipping over any * interceptors that may have become `null` calling `eject`. * * @param {Function} fn The function to call for each interceptor */ InterceptorManager.prototype.forEach = function forEach(fn) { utils.forEach(this.handlers, function forEachHandler(h) { if (h !== null) { fn(h); } }); }; module.exports = InterceptorManager;