提问者:小点点

有没有办法同步化解一个promise?(或一个可供选择的库)


我有一个用于验证字符串的方法,我希望该方法返回一个承诺,因为正在运行的验证可能是异步的。然而,我遇到的问题是性能问题,我希望在可能的情况下在相同的事件循环中解决Promission(例如:当没有异步验证要做时),但我希望接口保持一致(例如:始终返回Promission)。

下面的简化代码示例说明了我正在尝试的操作,但是它会导致前面提到的性能损失,因为即使可以同步执行验证,它仍然等待下一个事件循环来处理结果。

在我的特定用例中,这种性能损失太高了。

下面是我正在做的一个简化的(最小的)示例

// Array containing validation methods
const validations = [
  (value) => true, // Some validation would happen here
];
// Array containing asynchronous validation methods
const asyncValidations = []; // No async validations (but there could be)
const validate(value){
  // Run synchronous validations
  try {
    validations.forEach(validation => validation(value));
  catch(error){
    // Synchronous validation failed
    return Promise.reject();
  }
  if(asyncValidations){
    return Promise.all(asyncValidations.map(validation => validation(value));
  }
  // Otherwise return a resolved promise (to provide a consistent interface)
  return Promise.resolve(); // Synchronous validation passed 
}

// Example call
validate('test').then(() => {
  // Always asynchronously called
});


共2个答案

匿名用户

你提到了两件不同的事情:

>

  • 我希望接口保持一致

    [我想]永远回报一个承诺

    如果您希望避免异步行为(如果不需要的话),您可以这样做并保持API的一致性。但是你不能做的是“总是返回一个承诺”,因为不可能“同步解决一个承诺”。

    您的代码当前返回一个承诺,该承诺在不需要异步验证时被解析:

    // Otherwise return a resolved promise (to provide a consistent interface)
    return Promise.resolve(); // Synchronous validation passed
    

    您可以用以下代码替换该代码:

    return {then: cb => cb()};
    

    注意,这只是返回一个“thenable”的对象文字(即它有一个then方法),并将同步执行您传递给它的任何回调。但是,它并不回报一个承诺。

    您还可以通过实现then方法和/或catch方法的可选onrejected参数来扩展这种方法。

  • 匿名用户

    承诺异步解析的原因是它们不会炸毁堆栈。考虑以下使用承诺的堆栈安全代码。

    null

    console.time("promises");
    
    let promise = Promise.resolve(0);
    
    for (let i = 0; i < 1e7; i++) promise = promise.then(x => x + 1);
    
    promise.then(x => {
        console.log(x);
        console.timeEnd("promises");
    });