阅读 457

前端刷新token,重新发起请求,异步并发请求处理。

token过期后,需要前端携带旧的token去请求后端接口置换新的token

实现思路:协定错误码XXX,在响应拦截中拦截,发起刷新token请求,刷新完毕调用axios实例重新发起中断的请求。
我这里用的是401状态码

        //刷新token
        case 401:
        //发起刷新token的请求
            await getToken({}).then((res) => 
              if (res.code == 200) {//刷新成功 
                cookies.set("token", res.data); //替换新的token
                service(response.config);//重新发起由于token过期中断的请求
              } else {
                //刷新失败 重新登录
                if (doms2 == undefined) {
                  Message.error({
                    message: "登录失效,请重新登录",
                  });
                }
                //清除登录状态
                cookies.remove("infor");
                cookies.remove("token");
              }
            });

当token过期,一个页面异步同时发出多个请求时,多接口都携带旧token去请求,
不同时间返回401错误,挨个都去置换token造成被多次刷新异常。

解决思路:
  • 草根方案:

使用async、await函数把页面所有异步请求变成同步,等待上一个执行完毕再执行下一个请求。

  • 较完美方案:

在响应拦截器中第一个返回401执行刷新token的操作时候,设置一个正在更新token的状态,
其他的异步并发的请求返回401被拦截下来就不要去重复的执行更新token,用函数的形式暂存起来,
等待更新完毕再一起重新发起。

let isRefreshing = false;  // 定义一个是否正在刷新token的标记let retryRequests = [];// 定义一个空数组,承载请求队列

        //刷新token
        case 401:
          //判断是否正在更新token
          if (!isRefreshing) {
            isRefreshing = true; //更新状态
            //发起刷新token
            await getToken({}).then((res) => {
              if (res.code == 200) {
                cookies.set("token", res.data); //刷新成功
                //遍历缓存队列 发起请求 传入最新token
                retryRequests.forEach((cb) => cb(res.data));
                // 重试完清空这个队列
                retryRequests = [];
                service(response.config);
              } else {
                //刷新失败 重新登录
                if (doms2 == undefined) {
                  Message.error({
                    message: "登录失效,请重新登录",
                  });
                }
                //清除登录状态
                cookies.remove("infor");
                cookies.remove("token");
              }
            });
            // 正在刷新token,返回一个未执行resolve的promise
          } else {
             //这里的Promise里并没有调用resolve()去改变状态,而是直接push一个函数方法到数组
              //这样就可以把请求暂存起来,等待上面刷新token请求成功后,遍历 retryRequests数组
             //把新的token通过函数传参方式传入  调用方法执行重新请求
            return new Promise((resolve) => {
              // 将resolve放进队列,用一个函数形式来保存,等token刷新后调用执行
              retryRequests.push((token) => {
                response.config.headers.Authorization = token;
                resolve(service(response.config));
              });
            });
          }
          break;

以上已经实现异步请求并发时,暂存错误队列,等待token刷新成功后统一重新发起请求的问题。
有描述不清楚或者错误的地方欢迎提出指正。

6人点赞

vue开发问题解决



作者:户晓_web前端
链接:https://www.jianshu.com/p/bc3277494aa7
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐