场景
1、用户获取加密信息,比如自己的交易记录。
2、等待用户输入验证信息。
3、根据用户输入的结果,返回第一步请求结果
业务路径
用户在业务代码侧发起获取交易请求(promise)– 服务器返回需要二次验证(axios的response劫持获取结果)– — 弹出验证框,等待用户输入 — 根据结果通知业务层处理逻辑 — 完成
分析
方案一:弹窗验证后通知业务模块再次发起请求。
方案二:在axois的response劫持位置等待用户的输入,保持用户发起的promise一直处于Pending状态,根据用户输入的结果完成该次请求,返回结果。
由于获取加密信息的场景分布在不同的业务场景下,可能是获取交易记录,可能是其他私密的用户选择要加密的信息。如果使用方案一,代码逻辑耦合在一起;方案二则完全解耦,业务层和请求层分离。
结论选择方案二
难点
选择方案二,在数据请求层如何在服务器返回需要二次验证时
1、如何保持该请求一直处于pending状态,等待用户输入完成后再resolve/reject结果。[1]然后再次发送该请求到服务器获取结果,将该次结果返回给用户
关键代码
const timeout = async ms => new Promise(res => setTimeout(res, ms));
let next = false; // this is to be changed on user input
async function waitUserInput() {
while (next === false) await timeout(50); // pauses script
}
复制代码
定义一个异步timeout函数,一个等待用户输入waitUserInput函数。通过while控制流程一直处于await状态,且不会阻塞浏览器进程,用户通过控制判断的条件next来达到流程结束的目的最终返回结果。
2、如何将等待的请求再次发出 — axois.request(response.config)
实现
用户控制的变量next放在了store中,方便全局访问
next: 0, // 用户检验密码状态 0-无需检验 1-检验成功 2-检验失败
复制代码
在axois封装的位置
// 处理等待用户输入过程
const timeout = async (ms: number) => new Promise((res) => setTimeout(res, ms))
async function waitUserInput() {
while (store.state.user.next === 0) {
await timeout(50) // 等待用户输入
}
// 用户取消请求
if (store.state.user.next === 2) {
return Promise.resolve(false)
}
return Promise.resolve(true)
}
复制代码
在劫持位置
axois.interceptors.response.use(async (response) => {
if (code === '1') {
// 打开验证弹窗
store.commit('user/showValid', true)
// 等待用户输入
const userResult = await waitUserInput()
if (!userResult) {
store.state.user.next = 0
return {
code: -1,
message: '请求失败',
data: {},
}
}
// 用户输入验证通过后,返回请求结果
store.state.user.next = 0
// 重新发起该请求
return axois.request(response.config)
} else {
return response
}
}, errorHandler)
复制代码
在业务代码证中,验证通过后设置next状态为1
store.state.user.next = 1
复制代码
参考
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END