欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

js無痛刷新Token的實(shí)現(xiàn)

 更新時(shí)間:2022年03月18日 11:17:37   作者:沐夕花開  
本文主要介紹了js無痛刷新Token的實(shí)現(xiàn),文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

這個(gè)需求場(chǎng)景很常見,幾乎很多項(xiàng)目都會(huì)用上,之前項(xiàng)目也實(shí)現(xiàn)過,最近剛好有個(gè)項(xiàng)目要實(shí)現(xiàn),重新梳理一番。

需求

對(duì)于需要前端實(shí)現(xiàn)無痛刷新Token,無非就兩種:

  • 請(qǐng)求前判斷Token是否過期,過期則刷新
  • 請(qǐng)求后根據(jù)返回狀態(tài)判斷是否過期,過期則刷新

處理邏輯

實(shí)現(xiàn)起來也沒多大差別,只是判斷的位置不一樣,核心原理都一樣:

  • 判斷Token是否過期

    沒過期則正常處理

    過期則發(fā)起刷新Token的請(qǐng)求

    拿到新的Token保存

    重新發(fā)送Token過期這段時(shí)間內(nèi)發(fā)起的請(qǐng)求

重點(diǎn):

  • 保持Token過期這段時(shí)間發(fā)起請(qǐng)求狀態(tài)(不能進(jìn)入失敗回調(diào))
  • 把刷新Token后重新發(fā)送請(qǐng)求的響應(yīng)數(shù)據(jù)返回到對(duì)應(yīng)的調(diào)用者

實(shí)現(xiàn)

  • 創(chuàng)建一個(gè)flag isRefreshing 來判斷是否刷新中
  • 創(chuàng)建一個(gè)數(shù)組隊(duì)列retryRequests來保存需要重新發(fā)起的請(qǐng)求
  • 判斷到Token過期isRefreshing = false 的情況下 發(fā)起刷新Token的請(qǐng)求

    刷新Token后遍歷執(zhí)行隊(duì)列retryRequests

    isRefreshing = true 表示正在刷新Token,返回一個(gè)Pending狀態(tài)的Promise,并把請(qǐng)求信息保存到隊(duì)列retryRequests

import axios from "axios";
import Store from "@/store";
import Router from "@/router";
import { Message } from "element-ui";
import UserUtil from "@/utils/user";

// 創(chuàng)建實(shí)例
const Instance = axios.create();
Instance.defaults.baseURL = "/api";
Instance.defaults.headers.post["Content-Type"] = "application/json";
Instance.defaults.headers.post["Accept"] = "application/json";

// 定義一個(gè)flag 判斷是否刷新Token中
let isRefreshing = false;
// 保存需要重新發(fā)起請(qǐng)求的隊(duì)列
let retryRequests = [];

// 請(qǐng)求攔截
Instance.interceptors.request.use(async function(config) {
  Store.commit("startLoading");
  const userInfo = UserUtil.getLocalInfo();
  if (userInfo) {
    //業(yè)務(wù)需要把Token信息放在 params 里面,一般來說都是放在 headers里面
    config.params = Object.assign(config.params ? config.params : {}, {
      appkey: userInfo.AppKey,
      token: userInfo.Token
    });
  }
  return config;
});

// 響應(yīng)攔截
Instance.interceptors.response.use(
  async function(response) {
    Store.commit("finishLoading");
    const res = response.data;
    if (res.errcode == 0) {
      return Promise.resolve(res);
    } else if (
      res.errcode == 30001 ||
      res.errcode == 40001 ||
      res.errcode == 42001 ||
      res.errcode == 40014
    ) {
    // 需要刷新Token 的狀態(tài) 30001 40001 42001 40014
    // 拿到本次請(qǐng)求的配置
      let config = response.config;
    //   進(jìn)入登錄頁面的不做刷新Token 處理
      if (Router.currentRoute.path !== "/login") {
        if (!isRefreshing) {
            // 改變flag狀態(tài),表示正在刷新Token中
          isRefreshing = true;
        //   刷新Token
          return Store.dispatch("user/relogin")
            .then(res => {
            // 設(shè)置刷新后的Token
              config.params.token = res.Token;
              config.params.appkey = res.AppKey;
            //   遍歷執(zhí)行需要重新發(fā)起請(qǐng)求的隊(duì)列
              retryRequests.forEach(cb => cb(res));
            //   清空隊(duì)列
              retryRequests = [];
              return Instance.request(config);
            })
            .catch(() => {
              retryRequests = [];
              Message.error("自動(dòng)登錄失敗,請(qǐng)重新登錄");
                const code = Store.state.user.info.CustomerCode || "";
                // 刷新Token 失敗 清空緩存的用戶信息 并調(diào)整到登錄頁面
                Store.dispatch("user/logout");
                Router.replace({
                  path: "/login",
                  query: { redirect: Router.currentRoute.fullPath, code: code }
                });
            })
            .finally(() => {
                // 請(qǐng)求完成后重置flag
              isRefreshing = false;
            });
        } else {
          // 正在刷新token,返回一個(gè)未執(zhí)行resolve的promise
          // 把promise 的resolve 保存到隊(duì)列的回調(diào)里面,等待刷新Token后調(diào)用
          // 原調(diào)用者會(huì)處于等待狀態(tài)直到 隊(duì)列重新發(fā)起請(qǐng)求,再把響應(yīng)返回,以達(dá)到用戶無感知的目的(無痛刷新)
          return new Promise(resolve => {
            // 將resolve放進(jìn)隊(duì)列,用一個(gè)函數(shù)形式來保存,等token刷新后直接執(zhí)行
            retryRequests.push(info => {
                // 將新的Token重新賦值
              config.params.token = info.Token;
              config.params.appkey = info.AppKey;
              resolve(Instance.request(config));
            });
          });
        }
      }
      return new Promise(() => {});
    } else {
      return Promise.reject(res);
    }
  },
  function(error) {
    let err = {};
    if (error.response) {
      err.errcode = error.response.status;
      err.errmsg = error.response.statusText;
    } else {
      err.errcode = -1;
      err.errmsg = error.message;
    }
    Store.commit("finishLoading");
    return Promise.reject(err);
  }
);

export default Instance;

到此這篇關(guān)于js無痛刷新Token的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)js無痛刷新Token內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 原生JavaScript實(shí)現(xiàn)批量獲取表單數(shù)據(jù)

    原生JavaScript實(shí)現(xiàn)批量獲取表單數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了如何使用原生JavaScript實(shí)現(xiàn)批量獲取表單數(shù)據(jù),文中的示例代碼講解詳細(xì),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • 微信小程序?qū)崿F(xiàn)錄制、試聽、上傳音頻功能(帶波形圖)

    微信小程序?qū)崿F(xiàn)錄制、試聽、上傳音頻功能(帶波形圖)

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)錄制、試聽、上傳音頻功能(帶波形圖),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 帶有定位當(dāng)前位置的百度地圖前端web api實(shí)例代碼

    帶有定位當(dāng)前位置的百度地圖前端web api實(shí)例代碼

    這篇文章主要介紹了帶有定位當(dāng)前位置的百度地圖前端web api實(shí)例代碼 的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • 微信小程序 rich-text的使用方法

    微信小程序 rich-text的使用方法

    這篇文章主要介紹了 微信小程序 rich-text的使用方法的相關(guān)資料,這里提供屬性及方法并實(shí)現(xiàn)實(shí)例,幫助大家學(xué)習(xí)理解,需要的朋友可以參考下
    2017-08-08
  • IE 下的只讀 innerHTML

    IE 下的只讀 innerHTML

    可以先使用 DOM 的 createElement 方法創(chuàng)建 tr 和 td,然后對(duì) td 的 innerHTML 進(jìn)行相應(yīng)操作,最后用 appendChild 方法把創(chuàng)建的元素添加到 DOM 樹中。這樣在 IE 下就可以正常運(yùn)行了。
    2009-08-08
  • 微信小程序?qū)崙?zhàn)之網(wǎng)易云音樂歌曲詳情頁實(shí)現(xiàn)代碼

    微信小程序?qū)崙?zhàn)之網(wǎng)易云音樂歌曲詳情頁實(shí)現(xiàn)代碼

    本文給大家介紹了微信小程序?qū)W習(xí)記錄之網(wǎng)易云音樂歌曲詳情頁代碼實(shí)現(xiàn),代碼分為html、css和js部分,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • SpringMVC+bootstrap table實(shí)例詳解

    SpringMVC+bootstrap table實(shí)例詳解

    本文通過實(shí)例給大家介紹了SpringMVC+bootstrap-table,需要的朋友可以參考下
    2017-06-06
  • JS什么場(chǎng)景不適合箭頭函數(shù)

    JS什么場(chǎng)景不適合箭頭函數(shù)

    這篇文章主要介紹了JS什么場(chǎng)景不適合箭頭函數(shù),對(duì)箭頭函數(shù)感興趣的同學(xué),可以參考下
    2021-04-04
  • JS中FRAME的操作問題實(shí)例分析

    JS中FRAME的操作問題實(shí)例分析

    這篇文章主要介紹了JS中FRAME的操作問題實(shí)例分析,詳細(xì)講述了js針對(duì)frame框架操作中的各種訪問問題,需要的朋友可以參考下
    2014-10-10
  • form+iframe解決跨域上傳文件的方法

    form+iframe解決跨域上傳文件的方法

    下面小編就為大家?guī)硪黄猣orm+iframe解決跨域上傳文件的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-11-11

最新評(píng)論