前端專案中經常遇到請求輸入查詢場景,防抖與截流很好處理了頻繁輸入問題,但是不能解決最先發起請求結果後返回,覆蓋了最後一次的搜尋結果,導致搜尋結果不正確。我總結一下自己常用的兩種方法。
- 使用時間戳來過濾返回結果,如果請求回撥函式中的時間戳小於當前時間戳則返回,說明已經處理了之後的請求結果了,這個請求過時了。
// 遠端搜尋商品
searchGoods(data) {
if (!data) {
return
}
if (this.isRemote) {
const reqCount = new Date().getTime()
this.OrderInquireQuerySpuAndUnit({ keyWord: data }).then(res => {
if (reqCount < this.currentReqCount) {
return
}
if (res.data) {
if (res.data.length > 0) {
this.goodsList = res.data
}
}
}).catch(err => {
console.log(err)
}).finally(() => {
this.currentReqCount = reqCount
})
}
},
- 基於axios封裝統一的請求方法,後面發起的請求會取消之前等待返回結果的請求,需要多傳一個cancelTokenPath,表示當前同一個輸入元件發起的請求
export const getRequest = param => {
const { cancelTokenPath, ...restQuery } = (param && param.query) || {}
// cancelTokenPath是為了避免頁面中多處請求的同一個接,導致錯誤的取消
if (cancelTokenPath) {
const CancelToken = axios.CancelToken
const source = CancelToken.source()
if (store[cancelTokenPath]) {
store[cancelTokenPath].cancel('Canceled by the last request')
}
store[cancelTokenPath] = source
}
return new Promise((resolve, reject) => {
Vue.axios
.get(param.url, {
params: restQuery || {},
headers: param.headers || {},
cancelToken: cancelTokenPath && store[cancelTokenPath].token
})
.then(res => { resolve(res) })
.catch(err => {
reject(err)
})
})
}