夸克之书

  • 首页
  • 科普
  • 笔记
  • .NET/C#
  • 物联网
  • 算法
  • Linux
  • 树莓派
夸克之内,别有洞天
  1. 首页
  2. 默认
  3. 正文

解决js异步同时请求接口的问题

2021-08-20 3325点热度 1人点赞 0条评论

最近在实现refesh token,但是在前端页面请求刷新的时候遇到一个问题。

场景如下:刷新页面时,同时有几个接口在进行请求,由于refesh token的操作放在拦截器中,在接口请求时,判断当前token是否过期,如果token过期之后,进行token刷新操作。可想而知会发生什么问题。几个接口争先恐后的去使用refesh_token换取新的token,跑的快的,成功拿到新的token。跑的慢,只有拿第一个接口用过的refesh_token去刷新,服务器看到递过来的是已经用过了的 refesh_token,只有毫不犹豫的拒绝。

%title插图%num
请求失败

所以就需要一个机制,让换取token的操作依次执行,或者只需要执行一次。让第一次执行刷新token之后,后面接口发现token已经被刷新了,就不在去刷新token。

这时候就可以利用js Promise链式调用的特点去解决这个问题。具体思路就是返回Promise对象,通过调用Promise的then函数,返回需要的内容。具体原理的话,我描述不清楚,因为也是是个前端小菜鸡啊~~~所以有啥错误的地方,还请多多指教和包含。

上代码:

1、拦截器中判断token是否过期,过期就操作刷新

    let token = store.getters["account/token"];
    let timeNow = Math.round(new Date().getTime() / 1000);
    if (!requestUrlInIgnoreList(url) && (!token || token.expires_at - 60 <= timeNow)) {
      console.log("[Local]AccessToken expiring, start refresh token...");
      let newToken = await localRefreshToken();
      if (newToken) {
        console.log("[Local]Refresh successful, token is " + JSON.stringify(newToken));
        config.headers.Authorization = `Bearer ${newToken.access_token}`;
      } else {
        message.warning("认证已过期,请重新登录");
      }
    } else {
      if (!requestUrlInIgnoreList(url)) {
        config.headers.Authorization = `Bearer ${token.access_token}`;
      }
    }

2、token刷新类

class localAccount {
  refreshTokenPromise = null;

  refreshToken = async () => {
    if (this.refreshTokenPromise) {
      console.log("我是后来的,我也要刷新token...");
      return this.refreshTokenPromise.then(() => {
        let lastRefeshToken = store.getters["account/token"];
        return lastRefeshToken;
      });
    }
    let newToken = undefined;
    let oldToken = store.getters["account/token"];
    if (!oldToken || !oldToken.refresh_token) {
      return newToken;
    }
    this.refreshTokenPromise = request(POST_REFESH, METHOD.POST, {
      Token: oldToken.refresh_token,
    })
      .then((result) => {
        if (result && result.data.code == 0) {
          let userToken = {
            access_token: result.data.data.accessToken,
            refresh_token: result.data.data.refreshToken,
            token_type: result.data.data.tokenType,
            expires_at: result.data.data.expiresAt,
            profile: result.data.data.profile,
          };
          newToken = userToken;
          //设置用户
          if (newToken) {
            store.commit("account/setToken", newToken);
          }
          this.refreshTokenPromise = null;
          return newToken;
        }
      })
      .catch((err) => {
        console.error(err);
      });
    return this.refreshTokenPromise;
  };
}

通过定义一个全局的 refreshTokenPromise 对象,第一次请求时, refreshTokenPromise 对象为空,进行token刷新。由于封装的request本身也是一个异步请求,所以将request赋值给 refreshTokenPromise 。所以当第二个刷新请求过来之后,判断 refreshTokenPromise 是否为空,不为空的话,表示正在请求。使用then方法,返回从store取出第一次请求更新的token。

本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2022-01-25

afirefish

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论
放松一下
https://www.quarkbook.com/wp-content/uploads/2021/05/凤凰传奇-海底(Live).flac
分类
  • .NET/C#
  • Linux
  • 树莓派
  • 物联网
  • 科普
  • 笔记
  • 算法
  • 默认
最新 热点 随机
最新 热点 随机
维持宇宙的四种“力量”——关于四大基本力 MinGW图形安装界面里面没有mingw32 make.exe解决办法 Windows Server 2022安装Intel I225-V/I226-V驱动 System.Text.Json与Newtonsoft.Json Json序列化与反序列化性能对比 R86S散热改造 Windows移除多余输入法'Unknown Locale (qaa-Latn)'
Windows Server 2022安装Intel I225-V/I226-V驱动MinGW图形安装界面里面没有mingw32 make.exe解决办法维持宇宙的四种“力量”——关于四大基本力
记一次成功的Update(Oracle误Delete或Update数据还原) 严肃一点的排序算法(1) - 睡眠排序 解决Github pull和push慢 23种常见的设计模式(7):原型模式 将对象转化为Get请求字符串 树莓派.Net Core Iot入门系列篇(5):SPI
最近评论
afirefish 发布于 4 个月前(11月28日) 非常感谢,非常棒!
》随缘《 发布于 4 个月前(11月20日) 最新【一键处理】方法: https://github.com/MrXhh/VSTools/rele...
管理员 发布于 9 个月前(06月22日) emmmm....服务器好一点???
wking 发布于 10 个月前(05月23日) 请问贵博客是怎么优化的,网页响应速度非常快。我博客同样的WordPress和kratos主题,但点一...
去月球 发布于 1 年前(01月17日) 如果使用CSI的摄像头应该怎么修改命令呢
书签
  • 打赏
  • 毒鸡汤
  • 米店
  • 金鱼直播间

COPYRIGHT © 2022 quarkbook.com. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

蜀ICP备15036129号-9

登录
注册|忘记密码?