处理可能是异步的动态脚本

时间:2018-01-04 09:34:05

标签: javascript typescript asynchronous

我们有一个应用程序,可以让我们的用户能够在特定的“钩子”点编写自己的脚本。示例场景如下:

  • 我们提供2个表单字段
  • 用户可以添加自定义行为以在每个“Focus Gained”和“Focus Lost”事件
  • 上运行
  • 用户将自定义脚本写入第一个字段的“Focus Lost”,并执行一些关于该字段值的验证逻辑
  • 如果验证为false,那么我们的应用程序必须阻止字段更改并强制选择保留在现有字段上,直到提供有效值

如果验证逻辑像正则表达式匹配测试一样简单且同步,则此方案很容易处理。但是,如果用户添加了一些异步逻辑会发生什么(验证规则可能由Web服务提供)?那么你如何处理onFieldFocusLost钩子函数呢?使它async将迫使我们将await链一直传播到调用堆栈的顶部,直到调用序列无关紧要的点,这可能是很多层(已经实施并且很难改变)。

请注意,我们正在使用Typescript并将其编译为ES5,并且与IE10 +具有必需的兼容性(所有awaitgenerator shenanigans都可以正常填充。

最小例子:

// hook function whose implementation is provided by the user
function onFocusLost(field) {
  // implementation A
  return validRegex.test(field.value);

  // implementation B
  doXHR('/validRegex', 'GET', function(validRegex) {
    return validRegex.test(field.value);
  });
}

// hook function called by our application
inputField.addEventListener('focus-lost', function() {
  if (!onFocusLost(inputField)) {
    forceFocusToRemainOnField(inputField);
    return;
  }
  giveFocusToNextField(); // this must not be called if the user's onFocusLost logic returns false (synchronously or not)
});

1 个答案:

答案 0 :(得分:1)

一个可能的解决方案是检查钩子是否返回Promise,如果是,则阻止该字段,直到promise返回:

 inputField.addEventListener('focus-lost', async function(){
    const hook: boolean | Promise<boolean>  = onFocusLost();
    if(hook instanceof Promise){
      forceFocusToRemainOnField(inputField);
      alert("We are checking your input! Please wait");
      hook = await hook;
    }
    if(hook){
      //release field somehow
    } else {
     forceFocusToRemainOnField(inputField);
    }
 });

所以钩子看起来像这样:

 async function hook(){
   const res = await fetch("someapi");
   return res === "success";
}