场景
在页面中,可能会因为某些操作多次触发某个请求,如多次点击某按钮触发请求,实际上我们只需要最后一次请求的返回值,但是由于请求的耗时不一,请求未必会按发送的顺序返回,导致我们最终获取到的值 ≠ 最后一次发送请求的返回值。
根据项目经验,目前一共尝试过两种方法
1. 设置请求的唯一 id
2. 使用 axios 官方方法:AbortController
解决
1. 设置请求的唯一 id
为每个请求设置一个唯一 id,每触发一次请求,id+1,多次触发请求后,取值时根据请求 id 值来对应取值。
使用示例如下:
// 设置请求id初始值为0
sessionStorage.setItem('id', JSON.stringify(0))
/**
* 发送请求
* @param data 请求参数
*/
function query(data) {
loading.value = true
// priceId加1,并存储在session里
const priceId = JSON.parse(sessionStorage.getItem('id')) + 1
sessionStorage.setItem('id', JSON.stringify(priceId))
queryApi(data)
.then(res => {
// 根据session中的priceId, 取最后一次请求的返回值
if (priceId === JSON.parse(sessionStorage.getItem('id'))) {
// 处理业务逻辑
const { resultData } = res
}
})
.catch(err => {
// 业务处理逻辑
})
.finally(() => {
loading.value = false
})
}
const url = '/query/abc'
function queryApi(paramsObj) {
return httpInstance.post(url, paramsObj)
}
2. AbortController方法
AbortController 是 axios 官方提供的取消请求的 api,使用时注意:
1. 该 api 仅在 Axios 版本>=V0.22.0 时生效。
2. Axios 版本<V0.22.0 时请使用 CancelToken。
3. 允许取消一个或多个正在进行的请求,但如果请求已经成功响应则不能取消。
官网文档链接:取消请求 | Axios中文文档 | Axios中文网
使用示例如下:
// 用于存储当前的 AbortController 实例
let currentController = null
/**
* 发送请求
* @param data 请求参数
*/
function query(data) {
loading.value = true
// 取消之前的请求
if (currentController) {
currentController.abort()
currentController = null
}
const controller = new AbortController()
currentController = controller //重置AbortController
queryApi(data, controller.signal)
.then(res => {
const { resultData } = res
// 业务处理逻辑.....
loading.value = false
})
.catch(err => {
if (err.name === 'CanceledError') {
console.log('请求被取消', err.message)
} else {
console.error('请求失败', err)
loading.value = false
}
})
}
const url = '/query/abc'
function queryApi(paramsObj, signal) {
return httpInstance.post(url, paramsObj, {
signal: signal
})
}