axios 实现对请求失败的请求自动重新发起请求,对access_token过期自动刷token回来让之后的请求都不会有问题

本文介绍如何使用axios在请求失败时自动重试,并在access_token过期时刷新token,确保后续请求顺利进行。当refresh_token也过期时,则需重新登录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个如果refresh_token也过期了那就只能去登陆了,

直接上代码

import axios from 'axios';
import {getToken, setToken} from '@/libs/util'

const baseURL = 'http://localhost:8080/'

class HttpRequest {
  constructor(baseUrl = baseURL) {
    this.noAuthCode = 401
    this.noAuthorizetionUrl = '/error_network';
    this.mobileAuthorizeUrl = 'auth/getAuthUrl';
    this.refreshTokenUrl = '/auth/refreshToken';
    this.baseUrl = baseUrl;
    this.reqQueue = [];
    this.tokenExpired = false;
    this.refreshTokenExpired = false;
  }

  request(options) {
    const instance = axios.create();
    options = {...this.getInsideConfig(), ...options};
    this.interceptors(instance)
    return instance(options)
  }

  getInsideConfig() {
    const config = {
      baseURL: this.baseUrl,
      headers: {}
    }
    const token = getToken();
    if (token && token.accessToken) config.headers['Authentic'] = token.accessToken;
    return config;
  }

  interceptors(instance, uri) {
    const {noAuthCode,refreshTokenUrl,refreshTokenExpired} = this
    instance.interceptors.request.use(config => {
      return config
    }, error => {
      return Promise.reject(error)
    });
    instance.interceptors.response.use(res => {
      const {data} = res;
      if (data.code === noAuthCode) {
      	const originalUrl = config.url.replace(config.baseURL, '');
        return this.refreshToken(res, originalUrl);
      }
      this.destroy(uri);
      return {data, status}
    })
  }

  //这里是一个重点重发请求的重点
  refreshToken(res, uri) {
    const config = res.config;
    if (!this.tokenExpired) {//js 是单线程的不用考虑这里的并发问题,这里也只会有一个请求进来
      this.tokenExpired = true;
      const token = getToken();
      if (!token) return {};
      this.request({url: this.refreshTokenUrl, method: 'get', params: {refreshToken: token.refreshToken}})
        .then(({data}) => {
          // 没有权限(没有合法token)就需要去赋权 (可以是账号密码登录,也可以是别的操纵让此用户有权限)
          if (data.code === this.noAuthCode) {
            this.reqQueue = [];
            // 跳转到微信授权页面去授权 ,这里时第三方授权,需要授权后跳转到此页面来继续发起相应的请求
            this.goToAuthorizePage(res)
          } else {
            const token = data.data;
            setToken(token.accessToken, token.refreshToken);
            this.onAccessTokenFetched(token.accessToken);
          }
          this.tokenExpired = false;
        })
    }
    return new Promise((resolve) => {
      let fn = (accessToken) => {
        if (accessToken) {
          config.url = uri;
          config.headers['Authentic'] = accessToken;
          resolve(this.request(config))
        } else {
          resolve(res)
        }
      }
      this.addSubSubscriber(fn)
    })
  }

  onAccessTokenFetched(newToken) {
    if (!newToken) return
    this.reqQueue.forEach(callBackFn => callBackFn());
    this.reqQueue = []
  }

  goToAuthorizePage(config) {
    const originalHref = window.location.href;
    this.request({url: this.mobileAuthorizeUrl, method: 'get', params: {redirectUrl: originalHref}})
      .then(res => {
        if (res.status !== 200) {
          //跳转到授权失败的页面
        } else {
          if (res.data.code === 1) {
            //授权成功
            this.refreshTokenExpired = false;
          }
        }
      })
  }

  addSubSubscriber(fn) {
    this.reqQueue.push(fn)
  }

  destroy(uri) {
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值