前言

须要勾销反复申请的场景:

  • 比方输入框搜寻须要勾销上一次的反复申请
  • tab切换频繁获取数据列表接口时,接口反复申请
  • 就是用户频繁切换操作时,咱们调用都是同一个接口的时候,就需要先勾销上一次的接口申请,只申请用户最初一次操作的接口,不然雷同的接口反复申请,接口是异步的,到时就容易拿到数据不是最初一次操作想要的数据了

axios自身就封装了勾销事件

axios中文文档 勾销事件

axios勾销事件代码如下

  • 办法一、能够应用 CancelToken.source 工厂办法创立 cancel token,像这样:
const CancelToken = axios.CancelToken;const source = CancelToken.source();axios.get('/user/12345', {  cancelToken: source.token}).catch(function(thrown) {  if (axios.isCancel(thrown)) {    console.log('Request canceled', thrown.message);  } else {     // 处理错误  }});axios.post('/user/12345', {  name: 'new name'}, {  cancelToken: source.token})// 勾销申请(message 参数是可选的)source.cancel('Operation canceled by the user.');
  • 办法二、还能够通过传递一个 executor 函数到 CancelToken 的构造函数来创立 cancel token:
const CancelToken = axios.CancelToken;let cancel;axios.get('/user/12345', {  cancelToken: new CancelToken(function executor(c) {    // executor 函数接管一个 cancel 函数作为参数    cancel = c;  })});// cancel the requestcancel();

独自应用axios的时候,两个办法都能够,然而封装好axios办法在vue中全局调用时,办法一有个问题,axios的cancel办法会把行将要收回的申请勾销掉,所以用第二个办法

残缺axios封装代码如下:

import axios from 'axios'import UserModel from '../models/user'// 接口前缀const PREFIX = {  mock: 'https://yapi.comliq.net/mock/31/', // yapi mock 地址  development: 'http://xxx/', // qa环境  production: 'http://xxx/', // 生产环境}const env = process.env.NODE_ENVlet interfacePrefix = PREFIX[env] || PREFIX.production // 接口前缀/** * config 自定义配置项 * @param withoutCheck 不应用默认的接口状态校验,间接返回 response * @param returnOrigin 是否返回整个 response 对象,为 false 只返回 response.data * @param mock 是否应用 mock 服务 * @param timeout 接口申请超时工夫,默认10秒 * @param isCancelRequest 是否能够勾销申请 */const configDefault = {  returnOrigin: false,  withoutCheck: false,  mock: false,  timeout: 10000}// 创立申请器const service = axios.create(Object.assign({  baseURL: '',  responseType: 'json',  headers: {    'Content-Type': 'application/json;charset=utf-8',  },}, configDefault))// 增加申请拦截器service.interceptors.request.use(  request => {    const reqData = request.data || request.params    if (reqData && !request.canEmpty) { // 对申请参数进行解决,革除空参数      request.data = deleteEmpty(reqData)    }    // 检测接口,依据环境主动切换前缀    if (request.url.indexOf('http') === -1) {      if (request.url[0] === '/') {        request.url = request.url.substr(1)      }      request.url = `${env !== 'production' && request.mock ? PREFIX.mock : interfacePrefix}${request.url}`    }    // 若有做鉴权token,须要申请头主动加上token, 这个token本人封装获取的    request.headers.accessToken = UserModel.getToken()    return request  },  error => {    return Promise.reject(error)  },)// object对象寄存每次new CancelToken生成的办法let source = {}// 每次申请前都会把path放在此数组中,响应胜利后革除此申请pathlet requestList = []// 定义勾销办法function cancelRequest(path, allCancel) {  // 申请列表里存在此path,即发动反复申请,把之前的申请勾销掉  if (path && requestList.includes(path) && typeof source[path] === 'function') {    source[path]('终止申请')  } else if (!path && allCancel) {    // allCancel为true则申请列表里的申请全副勾销    requestList.forEach(el => {      source[el]('批量终止申请')    })  }}// 增加响应拦截器service.interceptors.response.use(  res => {    // 获取申请的api    const path = JSON.stringify(res.config.url)    // 申请实现后,将此申请从申请列表中移除    requestList = requestList.filter(item => !path.includes(item))    // HTTP 状态码 2xx 状态入口,data.code 为 200 示意数据正确,无任何谬误  },  error => { // 非 2xx 状态入口    return Promise.reject(error)  },)// 这里只做post封装演示,大家能够本人封装其余申请办法function requestFn(method, path, params = {}, options = {}) {  // 勾销上一次申请  if (requestList.length) {    cancelRequest(path)  }  // 设置isCancelRequest为ture, 申请前将path推入requestList  if (options.isCancelRequest) {    requestList.push(path)  }  if (method === 'post') {    return service.post(path, params, {      cancelToken: new axios.CancelToken(c => {        source[path] = c      }),      ...options    })  }}export const api = {  axios: service, // 原始 axios 对象  // 从新封装 get 函数,对立应用形式  get: (path, data, config) => service.get(path, { params: data, ...config }),  delete: (path, data, config) => service.delete(path, { data, ...config }),  post: (path, data, config) => requestFn('post', path, data, config),  put: (path, data, config) => service.put(path, data, config),}export default api

参考文献:

Vue中封装带有勾销申请的axios