前言
须要勾销反复申请的场景:
- 比方输入框搜寻须要勾销上一次的反复申请
- 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