vue3 實現無感重新整理token

梦初醒已无言發表於2024-09-06

問題一:如何防止多次重新整理token
透過設定一個變數isRefreshing 去控制是否在重新整理token的狀態
if (!isRefreshing) {
isRefreshing = true
return refreshToken().then((data:any) => {
setToken(data.token_type+' '+data.access_token);
//儲存token過期時換取新token值
localStorage.setItem('refresh-token',data.refresh_token)
// 重新整理token成功後重新傳送原來的請求
return service(response.config);
}).catch((error) => {
// 重新整理token失敗,跳轉到登入頁
// message.error(res.message)
message.error('您長時間未登入,請重新登入!')
goLogout();
return Promise.reject(error);
}).finally(()=>{
isRefreshing = false;
});
}
問題二:同時發起兩個或者兩個以上的請求時,其他介面怎麼解決
當第二個過期的請求進來是,token正在重新整理,這個時候我們可以先把這個請求存到一個陣列佇列中,想辦法讓這個請求處於等待中,一直等到重新整理的token後再逐個重試清空請求佇列,那麼如何讓這個請求處於等待中呢?我們可以藉助於Promise。將請求存進佇列中後,同時返回一個Promise,讓這個請求一直處於等待狀態,此時這個請求就會一直等,只要我們不執行resolve,這個請求就會一直在等待、當重新整理請求的介面返回來後,在呼叫resolve,逐個重試
service.interceptors.response.use(
(response: any) => {
//console.log('封裝地方的response',response)
//removePending( response.config );
const res = response.data;
// 後端status錯誤判斷
if (response.status == 200) {
if(response.data.hasOwnProperty('code')){
if (res.code == 200) {
return Promise.resolve(res);
} else if (res.code == 401) {
if(getToken()&&!isRefreshing){
isRefreshing= true;
removeToken()
// token過期,呼叫重新整理token的介面
return refreshToken().then((data:any) => {
setToken(data.token_type+' '+data.access_token);
//儲存token過期時換取新token值
localStorage.setItem('refresh-token',data.refresh_token)
//token重新整理後將陣列的方法重新執行
requests.forEach((cb:any)=>cb())
requests=[]
// 重新整理token成功後重新傳送原來的請求
return service(response.config);
}).catch((error) => {
// 重新整理token失敗,跳轉到登入頁
// message.error(res.message)
message.error('您長時間未登入,請重新登入!')
goLogout();
return Promise.reject(error);
}).finally(()=>{
isRefreshing= false;
});
}else{
//message.error(res.message)
// 返回未執行 resolve 的 Promise
return new Promise(resolve => {
// 用函式形式將 resolve 存入,等待重新整理後再執行
requests.push(() => {
resolve(service(response.config))
})
})
// goLogout()
// return Promise.reject(res);
}
}else if (res.code == 501) {
message.error(res.data)
return Promise.reject(res);
} else if (res.code == 500) {
if(!response.request.responseURL.includes('/admin/tender/token/refresh')){
message.error(res.message)
return Promise.resolve(res);
}else{
return Promise.reject(res);
}
}else {
// 錯誤狀態碼處理
message.error(res.message)
return Promise.reject(res);
}
}else{
//這裡針對excel的檔案流匯出
return Promise.resolve(response);
}
} else {
errorMessage(response)
return Promise.reject();
}
},
(error: any) => {
// Http錯誤狀態碼處理
// return Promise.reject(error);
if (error && error.response) {
// 1.公共錯誤處理
// 2.根據響應碼具體處理
errorMessage(error.response)
} else {
// 超時處理
if (JSON.stringify(error).includes('timeout')) {
// Message.error('伺服器響應超時,請重新整理當前頁')
error.message = '伺服器響應超時,請重新整理當前頁'
} else {
error.message = '連線伺服器失敗'
}
message.warning(error.message)
}

}

);

相關文章