前言
我们可能会遇到这样的场景:当用户切换页面时,上个页面存在pending中的请求。积少成多,如此会造成性能浪费,增加服务器压力。本文在于分享基于小程序提供的请求api及 axios 使用中如何取消不必要的请求。
基于Promise的requestTask封装
// request.js
function request(opt) {
const conf = { ... }
let reqTask = null // 保存 request 返回值,并挂载到 promise 上
const promise = new Promise((resolve, reject) => {
reqTask = request({
...conf,
success(res) {
const { data } = res
// ...
return resolve(data)
},
fail(err) {
return reject(err)
},
})
})
promise.reqTask = reqTask
return promise
}
export default request
// api.js
import request from './request'
export function fetchData() {
return request({ ... })
}
// index.js
import * as api from '../../api';
async fetchData() {
// 一般调用
await api.fetchData().then(response => { ... });
},
// usage
async fetchOtherData() {
const promise = api.fetchOtherData({ ... });
globalData['reqTask'] = promise.reqTask // 将 requestTask 挂到全局
await promise.then(response => { ... });
},
<script>
export default {
methods: {
handleClick() {
this.reqTask?.abort() // 取消请求
},
},
}
</script>
cancel token的使用
通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token
// file.js
import axios from 'axios'
uploadFile(context, files) {
const CancelToken = axios.CancelToken
for (let i = 0; i < files.length; i++) {
const file = files[i]
const promise = axios
.post('api', data, {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
file.cancel = c
// 全局挂载多个 cancel token
const cancels = []
cancels.push(c)
globalData['cancels'] = cancels
}),
})
.then(response => { ... })
.catch(thrown => {
if (axios.isCancel(thrown)) console.log('Request canceled', thrown.message);
else {
// 处理错误
}
})
},
// index.vue
<template>
<div>
<div v-for="file in files" :key="file.id">
<!-- cancel the request -->
<div @click="file.cancel" />
</div>
</div>
</template>
<script>
export default {
methods: {
handleClick() {
// 取消多个请求
for (let i = 0; i < this.cancels.length; i++) {
this.cancels[i]()
}
},
},
}
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。