维护你的请求队列,处理token异常
2024-10-19 22:35:01
前言
网络请求是开发中最基础也是最核心的需求,封装一个稳定且可用性高的请求也显得尤为重要。通常封装的内容除了入参之外,更多的是请求中的异常处理。本文分享下我在处理 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 异常的做法,如果你有更好的做法或建议,欢迎交流~
最新文章
- 172C
- Xcode 7 App Transport Security has blocked a cleartext HTTP 报错解决办法
- 关键字static和this
- 基于tcp/udp的协议
- UIMenuController 实现长按显示自定义菜单功能
- 使用selenium实现右键另存为保存文件
- 『jQuery』.html(),.text()和.val()的概述及使用
- 信号量和PV操作写出Bakery算法的同步程序
- SDUT2608(Alice and Bob)
- Ajax七层模型用途
- IOS面试问题总结
- webpack + vue + node 打造单页面(入门篇)
- 测试 ASP.NET Core API Controller
- python 菱形继承问题究极版
- redis 系列13 集合对象
- centos7编译linux的内核源码
- Docker Data Center系列(四)- 离线安装UCP和DTR
- Linux系统查看本机ip地址
- Linux下更换jdk和配置环境变量
- bzoj 1419 Red is good - 动态规划 - 概率与期望
热门文章
- 《Deep Learning of Graph Matching》论文阅读
- 沪江iKcamp出品微信小程序教学共5章16小节汇总(含视频)
- JavaScript常见的六种继承方式
- 通读Python官方文档之cgitb
- 在浏览器中使用ES6的模块功能 import 及 export
- 利用pandas选取某个属性符合指定条件的所有行
- spring boot Shiro JWT整合
- Webpack和Gulp,Webpack和Gulp的基本区别:
- 2019-2020-3 20174318张致豪《网络对抗技术》Exp2 后门原理与实践
- (转)协议森林09 爱的传声筒 (TCP连接)