从 WeRequest 登陆态管理来聊聊业务代码 原 荐
在开发微信小程序之前,个人从来没有接触过开发中涉及到第三方服务器交互的流程。在开发的过程本身倒是没有什么太大的意外,只是在维护服务器登陆状态这一点很讨厌。因为涉及到自身服务器的登录状态以及微信官方服务器登陆状态三方的关系。 下图是微信登陆机制: 在这种场景下,个人非常关注的点在于: 如何能够无感知的进行登陆(并且无多余请求)。微信的登陆状态倒是还好解决,可以利用 wx.checkSession 来进行判定,但是在与后台服务器交互时候,如果后台交互中返回 HTTP 状态码 401 (未授权)或者其他未登陆指示时候。则需要对其进行额外处理。 当时记得为了优雅的解决这个问题,想了很多方案,也与一些伙伴讨论过这个问题。虽然当时的确实现了无感知的登陆,但是要么需要多请求服务器,要么就是代码上实现逻辑过于复杂,代码维护。虽然不满意,但是在当时也没想到什么非常好的解决方法。 weRequest 自带状态管理的请求组件后面经过老大的介绍,看到这个组件时,我顿时眼前一亮,这正是我所需要的解决方案,该方案的图示如下: 只需要配置一些初始化项目,便可以直接拿去使用了。 // 导入
import weRequest from 'we-request';
weRequest.init({
// [可选] 存在localStorage的session名称,且CGI请求的data中会自动带上以此为名称的session值;可不配置,默认为session
sessionName: "session",// [可选] 请求URL的固定前缀;可不配置,默认为空
urlPerfix: "https://www.example.com/",136);">// [必填] 触发重新登录的条件,res为CGI返回的数据
loginTrigger: function (res) {
// 此处例子:当返回数据中的字段errcode等于-1,会自动触发重新登录
return res.errcode == -1;
},136);">// [必填] 用code换取session的CGI配置
codeToSession: {
// [必填] CGI的URL
url: 'user/login',136);">// [可选] 调用改CGI的方法;可不配置,默认为GET
method: 'GET',136);">// [可选] CGI中传参时,存放code的名称,此处例子名称就是code;可不配置,默认值为code
codeName: 'code',136);">// [可选] 登录接口需要的其他参数;可不配置,默认为{}
data: {},136);">// [必填] CGI中返回的session值
success: function (res) {
// 此处例子:CGI返回数据中的字段session即为session值
return res.session;
}
},136);">// [可选] 登录重试次数,当连续请求登录接口返回失败次数超过这个次数,将不再重试登录;可不配置,默认为重试3次
reLoginLimit: 2,136);">// [必填] 触发请求成功的条件
successTrigger: // 此处例子:当返回数据中的字段errcode等于0时,代表请求成功,其他情况都认为业务逻辑失败
0;
},136);">// [可选] 成功之后返回数据;可不配置
successData: // 此处例子:返回数据中的字段data为业务接受到的数据
return res.data;
},136);">// [可选] 当CGI返回错误时,弹框提示的标题文字
errorTitle: function(res) {
// 此处例子:当返回数据中的字段errcode等于0x10040730时,错误弹框的标题是“温馨提示”,其他情况下则是“操作失败”
0x10040730 ? '温馨提示' : '操作失败'
},136);">// [可选] 当CGI返回错误时,弹框提示的内容文字
errorContent: // 此处例子:返回数据中的字段msg为错误弹框的提示内容文字
return res.msg ? res.msg : '服务可能存在异常,请稍后重试'
},136);">// [可选] 当出现CGI错误时,统一的回调函数,这里可以做统一的错误上报等处理
errorCallback: function(obj,res) {
// do some report
},136);">// [可选] 是否需要调用checkSession,验证小程序的登录态过期,可不配置,默认为false
doNotCheckSession: true,136);">// [可选] 上报耗时的函数,name为上报名称,startTime为接口调用开始时的时间戳,endTime为接口返回时的时间戳
reportCGI: function(name,startTime,endTime,request) {
//wx.reportAnalytics(name,{
// time: endTime - startTime
//});
//request({
// url: 'reportCGI',
// data: {
// name: name,136);">// cost: endTime - startTime
// },136);">// fail: function() {
//
// }
//})
console.log(name + ":" + (endTime - startTime));
},136);">// [可选] 提供接口的mock,若不需使用,请设置为false。url为调用weRequest.request()时的url。mock数据的格式与正式接口提供的数据格式一致。
mockJson: {
url1: require("../../mock1.json"),url2: "../../mock2.json"),url3: "../../mock3.json")
}
// [可选] 所有请求都会自动带上globalData里的参数
globalData: function() {
return {
version: getApp().version
}
},136);">// [可选] session本地缓存时间(单位为ms),可不配置,默认不设置本地缓存时间
sessionExpireTime: 24 * 60 * 1000,136);">// [可选] session本地缓存时间存在Storage中的名字,可不配置,默认为 sessionExpireKey
sessionExpireKey: "sessionExpireKey"
})
export default weRequest;
使用时候直接拿到 weRequest 既可使用 weRequest.request({
url: 'order/detail',data: {
id: '107B7615E04AE64CFC10'
},
method: 'GET'
}).then((data)=>{
// 省略...
})
代码浅析简单的介绍一下 weRequest 库的实现机制,在这里代码简化一下,只会说明最主要调用的三个函数。
);
if (response != null) {
// 返回请求结果
return resolve(response);
}
}).catch((e) => {
// 异常处理机制
catchHandler(e,reject)
})
})
}
// sessionManager.main 方法
main() {
// 检查登陆态并返回, 如果登陆态过期,直接登陆,登陆成功后返回成功
return checkLogin().then(() => {
// 如果登陆态 ok, 把 config.doNotCheckSession 设置为 true。避免下次再次执行检查
return config.doNotCheckSession ? Promise.resolve() : checkSession()
},({title,content}) => {
errorHandler.doError(title,content);
return reject({title,content});
}).then(() => {
// 对checkSession 进行检查操作
return resolve();
},content})=> {
errorHandler.doError(title,content});
})
})
}
// responseHandler.response 方法
response ( res: wx.RequestSuccessCallbackResult,obj: IRequestOption,method: "request") {
if (res.statusCode === 200) {
// ... 省略代码
// 登录态失效,且重试次数不超过配置
if (config.loginTrigger!(res.data) &&
obj.reLoginCount !== undefined &&
obj.reLoginCount < config.reLoginLimit!) {
// 删除session
sessionManager.delSession();
if (method === "request") {
// 重新请求
return requestHandler.request(obj as IRequestOption);
}
}
}
}
我们可以利用结合官方网站的图示进行代码分析 如果用户从来没有登陆过时,或者 checkSession 过期:
用户登陆态未过期,再次打开小程序:
用户某次登陆后端,后端登陆态过期:
new Promise 内部封装异步操作之前在写关于异步代码操作时候,通常是基于 axios 直接返回 api 请求响应数据,对其进行正常和错误处理。当时多次异步操作从而返回正确与错误的流程却很少进行梳理。如果在一次请求内有多个异步操作:代码就会变得难以维护。事实上我们可以把 Promise 看成状态机。只有在某些情况下才会返回正确。 写出如上的代码,就可以在很多业务项内进行操作,诸如某些操作有前置权限请求,或者某些错误代码需要重新请求或者埋点等操作。
题外话很难有人能一次搞定业务需求,只有在它出现后,才知道什么他是它最需要的。业务代码也一样。 同时 weRequest 不是万能的,它符合大众的需求,但不一定符合每个业务的需求。你也可以根据代码改造甚至改进。 鼓励一下如果你觉得这篇文章不错,希望可以给与我一些鼓励,在我的 github 博客下帮忙 star 一下。?博客地址 参考weRequest 如何在Javascript中优雅的使用Async和Await进行错误的处理? 从不用 try-catch 实现的 async/await 语法说错误处理 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |