export const request = (options = {}) => {
//异步封装接口,使用Promise处理异步请求
return new Promise((resolve, reject) => {
let rd3_key = uni.getStorageSync('rd3_key') ? uni.getStorageSync('rd3_key') : ''
// 发送请求
uni.request({
url: baseUrl + options.url || '', //接收请求的API
method: options.method || 'GET', //接收请求的方式,如果不传默认为GET
data: options.data || {}, //接收请求的data,不传默认为空
data: {
...options.data,
rd3_key
},
header: {
'content-type': 'application/x-www-form-urlencoded', //修改此处即可
}
}).then(data => {
let [err, res] = data;
// if(res.data.code == 4001){
// post_login()
// }
if(res.data.code == 4001){
// return post_login().then(resolve, reject)
post_login()
}
resolve(res);
}).catch(error => {
reject(error);
})
})
}
下面这段
if(res.data.code == 4001){
// return post_login().then(resolve, reject)
post_login()
}
是登录失效后 接口请求返回4001,这时候会调用post_login() 重新获取最新的登录态完成静默登录,这个过程没什么问题,但是我写的onload事件里的那些业务接口却不会重新再发起请求了,请问这种情况 怎样统一处理下?
在解决你本来要问的问题之前,先说一个代码现在的问题。
看代码处理方式,
uni.request()
返回的显然是一个 Promise 或者 Promise Like。无所谓,都不需要再封一层 Promise。按原来的逻辑,处理成如果使用 async/await 的话,看起来逻辑会更清晰
接下来处理问题本身。问题本身要处理的是两个分支:
post_login
调用request
,不处理 4001 之类的错误(这个在问题中没明确描述)request
处理 4001 并尝试自动登录先说第 2 个,如果要自动登录,那么这个
request
的逻辑大概是这样:这段代码为了在
post_login()
后重试,有可能处理两次业务逻辑,所以需要封装到一个函数中以便复用,也就是上面示例代码中需要封装到businessRequest()
中的内容,显然request
中去掉尝试登录的逻辑,就是要封装的内容。所以这里有两种处理方式request
中移除尝试登录的代码,把这个事情交给一个新的外层封装requestWithLogin
去干request
中封装逻辑部分,像上面的示例那样(可以封装成一个局部函数,也可以是一个同级的外部函数)这里按 2 的方式来处理,单独写一个同级函数。要按 1 或局部函数的处理,只需要少量改动
到这一步,基本上已经解决问题了,但其实还有一个问题:如果在登录失效的情况下,同时发起多个请求,会怎么样?
同时发起多个请求,那这几个请求可能都需要重新登录,于是都会去尝试登录 —— 但实际只,只需要有一个去尝试登录就可以了。
怎么处理呢?加一个锁变量,检查到锁变量就等待一定时间直到解锁,然后再尝试登录(失败则直接返回)。这个逻辑可以写在
post_login
中最后要处理一个遗留的问题,如果在
post_login
中调用request
该怎么避免去尝试登录(否则可能造成无限递归)?其实很简单……
post_login
中去调用没尝试登录的那个requestDirectly
就可以了。不过
requestDirectly
是没 export 的(可能是为了保护),所以可以给request
加一个参数(在options
里或外都可以),根据这个参数来判断是否需要去尝试登录。