维护你的请求队列,处理token异常
程序员文章站
2022-06-21 19:29:52
前言 网络请求是开发中最基础也是最核心的需求,封装一个稳定且可用性高的请求也显得尤为重要。通常封装的内容除了入参之外,更多的是请求中的异常处理。本文分享下我在处理 异常方面的做法,通过维护请求队列,实现重发请求,减少 重复请求。 公共请求方法 下面以封装微信小程序请求作为例子,这是一个基础的公共请求 ......
前言
网络请求是开发中最基础也是最核心的需求,封装一个稳定且可用性高的请求也显得尤为重要。通常封装的内容除了入参之外,更多的是请求中的异常处理。本文分享下我在处理 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
过期后,发起一个 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 异常的做法,如果你有更好的做法或建议,欢迎交流~