axios封装(二)队列管理

在某些特定的场景(比如 即时搜索表格分页),会频繁的发起ajax请求,而由于ajax是异步API,所以返回的时序并不能够保证,这时候就需要实现一个ajax队列,在相同的请求发起时,取消处理上一个请求。

在使用 jquery.ajax 时,可以比较方便的使用 abort 方式中断处理ajax返回值,但是由于 axios 是依赖于 promise 的,导致了只能通过转换为 Promsie.reject 的方式中断处理。具体的代码如下:


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,
}

队列应用

队列一般结合函数防抖使用,在尽量减少请求次数的情况下,避免返回值顺序的错误

$(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);
    };
}

posted on 2018-06-04 14:59  smallcoder  阅读(2722)  评论(0编辑  收藏  举报

导航