日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

axios 并發請求時,刷新token的處理方法

作者:yunchong_zhao 更新時間: 2022-04-17 編程語言

背景: 后端設計token 過期時間是四個小時,但有一個用戶總是掛著賬號,然后就投訴了好幾次,賬號明明登錄著為啥就讓我重新登錄, 說什么token過期,哎 對客戶來說 這個確實是個難以忍受的 bug算是吧。

想起來大學的時候學過 軟件測試。什么是bug。bug就是沒有達到需求的都可以叫做是bug 當時可能有點廣泛哈。??

有點扯遠了其實這個問題 我們可以理清下思路哈

  1. 首先并發請求 肯定不至于 每一個都需要去刷新token 只需要第一個知道過期的那個請求去刷新就可以。
    這個時候需要我們怎么做呢?就是搞一個閘門,一旦有一個去刷新接口就 把閘門關閉。什么時候刷新完成 什么時候關閉
    這個可以通過一個變量去控制
let isFreshToken = true // 默認是打開
  1. 之前發送的沒有去刷新token的請求 我們還得緩存下來,等token 刷新完成之后 還得重新執行下 這些請求
let casheRequests = [];   // 請求隊列

有的童鞋可能會問, 那我之前的那些請求的參數去那里拿呢, 其實這個問題 axios的請求攔截和響應攔截的。config 中就已經給我們保存好了這些參數,我們只需要更換下 token即可

再其次就是我們 可以通過兩種方式判斷過期

  1. 判斷token時間有沒有過期,有的話 直接去刷新token
  2. 后端返回告訴我們token 過期

但是這兩種 用的處理方案都是一樣的。 我這里就是使用的第二種,在
axios的響應攔截中。由于后端告訴我們 token 過期了 我才去刷新 token

代碼實現步驟

這里需要寫一寫常用的封裝axios的一些東西

  1. 簡單封裝axios 請求
let isFreshToken = true // 是否刷新token 默認是打開
let casheRequests = [];   // 請求隊列
const request = axios.create({
      baseURL: apiUrl,  // 這里寫的是你們的接口地址
      timeout: 10000,
      headers: {
        Accept: 'application/json, text/plain, */*',
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      responseType: 'json'
    })
request.defaults.headers['token'] = localStorage.getItem('token')
  1. 然后就是響應攔截的設置了
// 響應攔截
request.interceptors.response.use(res => {
	const { data, status, config } = res;
	if(status == 200) { // 請求狀態成功
		if(data.Code == 4441) { // token過期
			if(isFreshToken) {//token可以刷新 一次并發只能有一個刷新
			    isFreshToken = false; // 把開關關閉
			    // 刷新token 是一個 返回promise的請求接口的方法 這個是自定義的 看你們自己的項目來定
			    reFreshToken().then(result => {
					isFreshToken = true // 方法重新打開
					let token = result.token; // 拿到新的token
					// 重新賦值token
					localStorage.setItem('token', token);
					// 重新執行 之前緩存的方法數組 使用最新的token
					casheRequests.forEach(cb => cb(token))
					// 重置為空 降緩存的請求方法
					casheRequests = []
					// 然后重新執行本次的方法
					config.headers['token']= token // 使用最新的token
					return request(config); 
					
				})
				//
			} else {
               // token 正在刷新中 其他的請求先放在隊列中
               return new Promise(resolve => {
					// 將resolve放進隊列,用一個函數形式來保存,等token刷新后直接執行
		              casheRequests.push((token) => {
		                config.headers['token']= token
		                resolve(request(config))
		              })
				})
			}
		}
		return data
	}
}

大概的思路就是這樣的呢, 但還會有點瑕疵, 哎怎么說呢。

心里心外誰來言,花開花落又一年
關注我 持續更新前端知識

不管是熱愛也好工作也罷, 程序員還是要熱愛生活的,好好愛自己。 寫了這么多博客 也有點疲倦了,可能熱情過后彼此過后都會疲倦吧。

原文鏈接:https://yunchong.blog.csdn.net/article/details/122347719

欄目分類
最近更新