当链接多个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并没有真正给我们提供选择。接下来。
答案 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?
});