维护你的请求队列,处理token异常

网络请求是开发中最基础也是最核心的需求,封装一个稳定且可用性高的请求也显得尤为重要。通常封装的内容除了入参之外,更多的是请求中的异常处理。本文分享下我在处理 token 异常方面的做法,通过维护请求队列,实现重发请求,减少 token 重复请求。

公共请求方法

下面以封装微信小程序请求作为例子,这是一个基础的公共请求:

common({ baseUrl = this.baseUrl, method, url, data, header }) { return new Promise((resolve, reject) => { let token = wx.$utils.getStorageToken() wx.request({ method, url: baseUrl + url, data, header: { \'Content-Type\': \'application/x-www-form-urlencoded\', token, ...header }, success: (res) => { if (res.data.code == 0 || res.data.code == 500) { // 失败 reject(res.data) } if (res.data.code == 1) { // 成功 resolve(res.data) } if (res.data.code == -1) { // token过期 // token过期处理 } }, fail: reject }) }) } token过期重发请求

getToken 方法内部会将 token 存储到本地中

success: (res) => { res = res.data if (res.code == 0) { reject(res.msg) } if (res.code == 1) { wx.setStorageSync(\'loginInfo\', res.data) resolve(res.data.token) } }

当 token 过期,在等待 getToken 后,再次发送请求,将结果 resolve

common({ baseUrl = this.baseUrl, method, url, data, header }) { return new Promise((resolve, reject) => { let token = wx.$utils.getStorageToken() wx.request({ method, url: baseUrl + url, data, header: { \'Content-Type\': \'application/x-www-form-urlencoded\', token, ...header }, success: async (res) => { if (res.data.code == 0 || res.data.code == 500) { reject(res.data) } if (res.data.code == 1) { resolve(res.data) } if (res.data.code == -1) { + await this.getToken() + this.common({ baseUrl, method, url, data, header }) + .then(resolve) + .catch(reject) } }, fail: reject }) }) }

这样看起来好像没什么问题,但由于内部没有限制处理,有 n 个请求就会发起 n 个 getToken 请求。这当然不是我们想要的,就像下面这样重复发起了两次 wxLogin:

维护你的请求队列,处理token异常

维护请求队列

理想的情况是:token 过期后,发起一个 getToken 请求。每当有请求进来,将它存入队列中,等待 getToken 完成,执行队列中的所有请求。

这样我们需要定义请求队列 qeueu 和token 请求的标识 isTokening,还有加入队列方法 pushQeueu 和执行队列方法 execQeueu。

{ qeueu: [], isTokening: false, pushQeueu({ method, url, data, header, resolve, reject }){ this.qeueu.push({ data: { method, url, data, header }, resolve, reject, request: (data)=> this.common(data) }) }, execQeueu(){ this.qeueu.forEach((item, index) => { item.request(item.data) .then(item.resolve) .catch(item.reject) // 执行完任务后 清空队列 if(index === this.qeueu.length-1){ this.qeueu.length = 0 } }) } }

处理如下:

common({ baseUrl = this.baseUrl, method, url, data, header }) { return new Promise((resolve, reject) => { let token = wx.$utils.getStorageToken() wx.request({ method, url: baseUrl + url, data, header: { \'Content-Type\': \'application/x-www-form-urlencoded\', token, ...header }, success: async (res) => { if (res.data.code == 0 || res.data.code == 500) { reject(res.data) } if (res.data.code == 1) { resolve(res.data) } if (res.data.code == -1) { + this.pushQeueu({ method, url, data, header, resolve, reject }) + if(this.isTokening === false){ + this.isTokening = true + await this.getToken() + this.isTokening = false + this.execQeueu() + } } }, fail: reject }) }) }

发起 getToken 请求后,将 isTokening 置为 true 表示正在请求中。当再有请求进入时,则不会再重复发送 getToken。

处理getToken错误

getToken 在发生错误时,我们应当捕获错误,不继续执行请求队列并清空队列

if (res.data.code == -1) { this.pushQeueu({ method, url, data, header, resolve }) if(this.isTokening === false){ this.isTokening = true let err = await this.getToken().then(res => null).catch(err => err) if(err){ this.qeueu.length = 0 console.error(err) }else{ this.isTokening = false this.execQeueu() } } } 写在最后

以上是我在处理 token 异常的做法,如果你有更好的做法或建议,欢迎交流~

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwggyg.html