一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情。
背景
使用axios
调用接口时,接口经过拦截判断到缺少认证身份信息(jwt之类)会有一个调认证接口的操作。就目前不加限制来看,在缺少认证信息的情况下,当前页面并发了6个接口的话,就会调用6次认证接口,属实浪费。那应该如何去优化这个过程呢?
思考
需求1:按正常逻辑来说,无论多少个接口,同一时间都应该只调用一次认证接口才对
需求2:调用认证接口期间,后面发起的接口理应等待认证接口调用完成才继续执行,保证接口都携带上身份信息
综上所述,我们需要一个拥有单例模式+队列的功能,所以这个东西要怎么实现呢?
很简单,那就是Promise
,很巧的是,调用axios
相应函数会返回一个Promise
实例,那么我们只要保存这个返回值,让后续接口到await
起来,等到认证接口调用完毕后,才释放接口队列。
let jwt
let lock = null
http.interceptors.request.use(
async config => {
// 判断是否有jwt
if (!jwt) {
// 生成锁住
if (!lock) {
lock = fetchJWT()
}
try {
jwt = await lock // 锁住防止并发
// 每次并发完成清除Promise
lock = null
} catch (e) {
// 获取jwt失败,跳转登录页重新登录
login()
}
}
config.headers.Authorization = `Bearer ${jwt}`
return config
}
)
原理分解出来后,实现过程就非常简单
题外话
除了axios
之外,还有一个叫flyio
的库,它自带了lock
功能,整体实现方式简单易懂,采取分层设计,让跨端更加简单,感兴趣的可以试下,也可以看看下面分析该库源码的文章