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;