前言
咱们可能会遇到这样的场景:当用户切换页面时,上个页面存在 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>
refs
改良异步封装:解决带返回值的异步调用
axios 中文文档