在某些特定的場景(好比 即時搜索
,表格分頁
),會頻繁的發起ajax請求,而因爲ajax是異步API,因此返回的時序並不可以保證,這時候就須要實現一個ajax隊列,在相同的請求發起時,取消處理上一個請求。javascript
在使用 jquery.ajax
時,能夠比較方便的使用 abort
方式中斷處理ajax返回值,可是因爲 axios
是依賴於 promise
的,致使了只能經過轉換爲 Promsie.reject
的方式中斷處理。具體的代碼以下:java
import axios from 'axios'; import Qs from 'qs'; // 上一篇文章中定義的錯誤處理文件 import httpErrorHandler from './httpErrorHandler'; const instance = axios.create(); // 請求隊列 const queue = []; // axios內置的中斷ajax的方法 const cancelToken = axios.CancelToken; // 拼接請求的url和方法,一樣的url+方法能夠視爲相同的請求 const token = (config) =>{ return `${config.url}_${config.method}` } // 中斷重複的請求,並從隊列中移除 const removeQueue = (config) => { for(let i=0, size = queue.length; i < size; i++){ const task = queue[i]; if(task.token === token(config)) { task.cancel(); queue.splice(i, 1); } } } //添加請求攔截器 instance.interceptors.request.use(config=>{ removeQueue(config); // 中斷以前的同名請求 // 添加cancelToken config.cancelToken = new cancelToken((c)=>{ queue.push({ token: token(config), cancel: c }); }); return config; }, error => { return Promise.reject(error); }); //添加響應攔截器 instance.interceptors.response.use(response=>{ // 在請求完成後,自動移出隊列 removeQueue(response.config); return response.data }, httpErrorHandler); /** * 封裝後的ajax post方法 * * @param {string} url 請求路徑 * @param {object} data 請求參數 * @param {object} config 用戶自定義設置 * @returns */ function post (url, data, config = {}) => { return instance.post(url, data, config) } /** * 封裝後的ajax get方法 * * @param {string} url 請求路徑 * @param {object} params 請求參數 * @param {object} config 用戶自定義設置 * @returns */ function post (url, params, config = {}) => { return instance.get(url, {params}, config) } export default { post, get, }
隊列通常結合函數防抖使用,在儘可能減小請求次數的狀況下,避免返回值順序的錯誤jquery
$(input).on('input', evt => { // 在用戶不斷的輸入過程當中,當暫停輸入100ms才發起ajax,在發起ajax的同時,中斷上一個查詢keyword的ajax debounce(()=>{ get('http://baidu.com', {keyword: evt.target.value}) }) }) // 定義一個防抖函數 function debounce(fn, step = 100) { let timeout = null; return function () { clearTimeout(timeout); timeout = setTimeout(() => { fn.apply(this, arguments); }, step); }; }