更多文章
一般情況下,在 vue 中結合 axios 的攔截器控制 loading 展示和關閉,是這樣的:
在 App.vue
配置一個全局 loading。
<div class="app">
<keep-alive :include="keepAliveData">
<router-view/>
</keep-alive>
<div class="loading" v-show="isShowLoading">
<Spin size="large"></Spin>
</div>
</div>
同時設置 axios 攔截器。
// 添加請求攔截器
this.$axios.interceptors.request.use(config => {
this.isShowLoading = true
return config
}, error => {
this.isShowLoading = false
return Promise.reject(error)
})
// 添加響應攔截器
this.$axios.interceptors.response.use(response => {
this.isShowLoading = false
return response
}, error => {
this.isShowLoading = false
return Promise.reject(error)
})
這個攔截器的功能是在請求前打開 loading,請求結束或出錯時關閉 loading。
如果每次只有一個請求,這樣運行是沒問題的。但同時有多個請求並發,就會有問題了。
舉例:
假如現在同時發起兩個請求,在請求前,攔截器 this.isShowLoading = true
將 loading 打開。
現在有一個請求結束了。this.isShowLoading = false
攔截器關閉 loading,但是另一個請求由於某些原因並沒有結束。
造成的后果就是頁面請求還沒完成,loading 卻關閉了,用戶會以為頁面加載完成了,結果頁面不能正常運行,導致用戶體驗不好。
解決方案
增加一個 loadingCount
變量,用來計算請求的次數。
loadingCount: 0
再增加兩個方法,來對 loadingCount
進行增減操作。
methods: {
addLoading() {
this.isShowLoading = true
this.loadingCount++
},
isCloseLoading() {
this.loadingCount--
if (this.loadingCount == 0) {
this.isShowLoading = false
}
}
}
現在攔截器變成這樣:
// 添加請求攔截器
this.$axios.interceptors.request.use(config => {
this.addLoading()
return config
}, error => {
this.isShowLoading = false
this.loadingCount = 0
this.$Message.error('網絡異常,請稍后再試')
return Promise.reject(error)
})
// 添加響應攔截器
this.$axios.interceptors.response.use(response => {
this.isCloseLoading()
return response
}, error => {
this.isShowLoading = false
this.loadingCount = 0
this.$Message.error('網絡異常,請稍后再試')
return Promise.reject(error)
})
這個攔截器的功能是:
每當發起一個請求,打開 loading,同時 loadingCount
加1。
每當一個請求結束, loadingCount
減1,並判斷 loadingCount
是否為 0,如果為 0,則關閉 loading。
這樣即可解決,多個請求下有某個請求提前結束,導致 loading 關閉的問題。