在alovajs中无感刷新token

alova是一个轻量级的请求策略库,旨在简化接口的管理和使用。你可以通过简单配置参数,即可实现复杂请求如请求共享、分页请求、表单提交、断点续传等,无需编写大量代码,提高开发效率,应用性能,减轻服务端压力。

在请求时我们经常需要通过token授权登录,并在token过期时通过refresh_token刷新token,这边我们来讨论下如何通过alova来无感刷新token,即当发现token过期时自动刷新token,在请求发起处不会感觉到token已刷新。

目前已推出token认证模块,只需要简单配置就可以实现无感token刷新了,建议直接使用即可。详情查看->

以下是实现无感刷新token的两种思路,每种思路都实现了token在刷新期间让其他请求等待的功能。

在前端判断token过期

这种是在前端判断token是否过期,这通常在登录时有返回token过期时间时使用,思路是在beforeRequest中判断token是否过期,已过期则先刷新token后继续发送请求,它的优点是不会接收到token过期的响应,因此也不需要重复发送请求。

let token = '', refreshToken = '', tokenRefreshing = false, waitingList = [];
const alovaInstance = createAlova({
  // ...
  beforeRequest: async method => {
    if (getCache('token_expire_time') < Date.now() && method.meta?.authType !== 'refreshToken') { // token过期
      if (tokenRefreshing) {
        // 如果正在刷新token,则等待刷新完成后再发请求
        console.log('正在刷新token,等待请求');
        await new Promise(resolve => {
          waitingList.push(resolve);
        });
      }

      try {
        tokenRefreshing = true;
        const { refreshToken: newRefreshToken, token: newToken } = await tokenRefresh({ refreshToken });
        // 保存新的token和refreshToken
        token = newToken;
        refreshToken = newRefreshToken;

        tokenRefreshing = false;
        // 刷新token完成后,通知等待列表中的请求
        waitingList.forEach(resolve => resolve());
        waitingList = [];
      } catch(error) {
        // 刷新token失败,可以处理跳转到登录界面等操作
        // ...
      }
    }

    method.config.headers.Authorization = token;
  },
})

在这里tokenRefresh请求method添加了authType = 'refreshToken'的meta数据作为标识,才能通过请求。

export const tokenRefresh = () => {
  const method = alovaInst.Get('/refresh-token', {
    localCache: null
  });
  method.meta = {
    authType: 'refreshToken'
  };
  return method;
}

通过服务端返回的状态判断token过期

这种方式是通过服务端的返回状态判断token是否过期,这通常在登录时没有返回token过期时间时使用,思路是在responded.onSuccess中通过返回状态判断token是否过期,已过期则刷新token后再次发送请求,它的优点是比较准确,但也会有重复的请求发送。

let token = '', refreshToken = '';
let tokenRefreshing = false; // 正在刷新token,让其他请求先等着
let waitingList = [];
const alovaInst = createAlova({
  // ...
  beforeRequest: async ({ url, config, meta }) => {
    console.log(url, '正在请求');
    // 如果正在刷新token,则等待刷新完成后再发请求
    if (tokenRefreshing && meta?.authType !== 'refreshToken') {
      console.log('正在刷新token,等待请求');
      await new Promise(resolve => {
        waitingList.push(resolve);
      });
    }
    config.headers.Authorization = token;
  },
  responsed: async (response, method) => {
    if (response.status === 401) { // token过期
      console.log(method.url, 'token失效,重新获取token');
      try {
          // 这边防止请求多次刷新token,把在token刷新完成前发送的拦截并等待
          if (tokenRefreshing) {
            console.log('正在刷新token,等待请求');
            await new Promise(resolve => {
              waitingList.push(resolve);
            });
          })
        tokenRefreshing = true;
        const { token: newToken, refreshToken: newRefreshToken } = await refreshToken({ refreshToken });
        token = newToken;
        refreshToken = newRefreshToken;

        tokenRefreshing = false;
        waitingList.forEach(resolve => resolve());
        waitingList = [];
        console.log('已获得新token并保存', token, `再重新访问${method.url}`);

        // 这里因为是重新请求原接口,与上一次请求叠加会导致重复调用transformData,因此需要将transformData置空去除一次调用
        const methodTransformData = method.config.transformData;
        method.config.transformData = undefined;
        const dataResent = await method;
        method.config.transformData = methodTransformData;
        return dataResent;
      } catch(error) {
        // 刷新token失败,可以处理跳转到登录界面等操作
        // ...
      }
    }
    return response.json();
  },
});

至此alova的两种刷新token的思路都实现了,在请求发起处无感知token刷新。

想学习更多 alovajs 的用法,欢迎来alova 官网学习。如果你也喜欢 alovajs,请在Github 仓库中贡献一颗 star,这对我们非常重要。

如果觉得文章对你有帮助,请别吝啬你的赞和评论哈,说说你对 alovajs 怎么看的,或者可以问一些问题,我会尽量回答的,你的支持是我创作的最大动力!哈哈哈哈哈哈~

欢迎加入交流社区

有任何问题,你可以加入以下群聊咨询,也可以在github 仓库中发布 Discussions,如果遇到问题,也请在github 的 issues中提交,我们会在最快的时间解决。

同时也欢迎贡献你的一份力量,请移步贡献指南

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值