嵌套的承诺何时需要返回?

时间:2018-11-26 15:28:44

标签: javascript node.js promise

当链接多个then语句时,我很难理解何时需要将值返回到下一个then语句以及何时将其自动传递。 (对我而言)困惑是当我在then语句中有诺言而不是诺言时。

这是在节点环境中-一个快速应用程序(更具体地说,是由HTTP请求触发的Firebase函数)-因此,我最终将res.send()赋予一些价值。

// Do I need to return mainFunction()?
mainFunction()
  .then(resultOfMyFunction => {
    // I want the next "then" to wait for the response from this block
    // Do I have to return asyncFunction() or just the value below?
    asyncFunction().then(resultOfPromise => {
      // Do I return resultOfPromise?
    }).catch(error => {
      // If I return this error, will it go to the mainFunction catch block?
      return error
    })
  }).then(resultOfPromise => {
    // This is blocking, so the next "then" should wait for the value
    return synchronousFunction(resultOfPromise)
  }).then(resultOfSynchronousFunction => {
    // End of function - do I need to return resultOfSynchronousFunction?
  }).catch(error => {
    // Do I need to return error?
  })

我知道我们不应该嵌套promise,但是当您需要链接多个不同的数据库调用(其中每个调用都是promise并且需要等待来自一个调用的数据)时,Firebase并没有真正给我们提供选择。接下来。

3 个答案:

答案 0 :(得分:2)

  

(对我而言)困惑是当我在then语句中有诺言而不是诺言时。

只要您在then内或异步函数中有承诺,就必须 返回给它。否则,拒绝(异步函数和promise中的抛出错误)将被吞没并最终陷入全局钩子,而不会给调用您的代码的人提供处理错误的机会。

同步函数没有这样的限制-仅当您想重用其返回值时才返回同步代码,因为抛出的错误由then自动处理。

  // If I return this error, will it go to the mainFunction catch block?

承诺真的很不可思议。返回值是错误/成功(已拒绝/已实现)状态在两次调用之间传播的方式,因此,如果您不返回该值,则mainFunction不会进入其catch块。

如果您希望它进入其catch块-返回值必须是一个最终会被拒绝的promise-为此,您需要在内部.catch块中重新抛出错误或删除{{1 }}。

答案 1 :(得分:0)

在前两个then()

中,您实际上并不需要匿名函数

您可以通过将函数引用传递给then()来做到这一点

mainFunction()
  .then(asyncFunction)
  .then(synchronousFunction)
  .then(resultOfSynchronousFunction => {
    // consume resultOfSynchronousFunction or return to next then()
  }).catch(error => {
    // Do I need to return error?
    // only if this is not final catch block
  })

答案 2 :(得分:-1)

我认为您想要这样的东西。我假设This is blocking表示synchronousFunction不是异步的。在这种情况下,不需要像承诺那样消费它。

mainFunction()
  .then(resultOfMyFunction => {
    //return promise from async function
    return asyncFunction();
  })
  .then(resultOfPromise => {
    let resultOfSynchronousFunction = synchronousFunction(resultOfPromise);
    // End of function
  })
  .catch(error => {
    // Do I need to return error?
  });

如果您想返回resultOfSynchronousFunction,则应阅读How do I return the response from an asynchronous call?

如果您想返回synchronousFunction的异步版本,则需要将其包装在promise中:

mainFunction()
  .then(resultOfMyFunction => {
    //return promise from async function
    return asyncFunction();
  })
  .then(resultOfPromise => {
    return new Promise((resolve, reject) => {
       let resultOfSynchronousFunction = synchronousFunction(resultOfPromise);
       // End of function
       resolve(resultOfSynchronousFunction);
    });
  })
  .then(resultOfSynchronousFunction => {})
  .catch(error => {
    // Do I need to return error?
  });

如果您想在synchronousFunction之后运行另一个异步调用,则更好的模式是:

mainFunction()
  .then(resultOfMyFunction => {
    //return promise from async function
    return asyncFunction();
  })
  .then(resultOfPromise => {

       let resultOfSynchronousFunction = synchronousFunction(resultOfPromise);
       // End of function
       return anotherAsyncCall(resultOfSynchronousFunction );
  })
  .then(resultOfanotherAsyncCall => {})
  .catch(error => {
    // Do I need to return error?
  });