请求发出,等到用户交互验证后,再返回该请求的结果

场景

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
复制代码

参考

www.coder.work/article/269… [1]

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享