节点蓝鸟承诺链接

node bluebird promise chaining

我是新来的承诺。我正在尝试使用 promise 将查询发送到 mysql db。在一些查询之后,我将使用查询的结果,进行一些计算,然后将输出用作下一个查询的一些参数。看起来像下面这样:

firstQuery(). then(secondQuery). then(thirdQuery). then(fourthQuery). ...

比如说,在fourthQuery中,我需要使用来自firstQuery和secondQuery的结果,并且会有一些额外的计算。我应该怎么做?

我知道我可以通过将参数传递给函数来获得先前承诺的结果:

then(thirdQuery). then(cal("I can only get output from thirdQuery here")). then(fourthQuery("pass output from cal"))

在这种情况下,我不认为 Promise 比回调有任何优势,因为我总是可以编写一个函数来简化重复的回调。

在这种非常常见的情况下,您可以将每个 then 的结果移到 promise 之外,然后它们将在剩余的 then 块中访问。

例如:

function first() { ... }
function second() { ... }
function third() { ... }
function fourth(firstValue, secondValue) { ... }

var firstResponse, secondResponse;
first()
.then(function(_firstResponse) {
  firstResponse = _firstResponse;
  return second();
})
.then(function(_secondResponse) {
  secondResponse = _secondResponse;
  return third();
})
.then(function() {
  return fourth(firstResponse, secondResponse);
})

如果你可以重写 firstQuery、secondQuery 等你可以做这样的事情

function firstQuery(allResult = {}) {
    return doTheQuery()
    .then(result => {
        allResult.first = result;
        return result;
    });
}
function secondQuery(allResult = {}) {
    return doTheQuery()
    .then(result => {
        allResult.second = result;
        return result;
    });
}
function thirdQuery(allResult = {}) {
    return doTheQuery()
    .then(result => {
        allResult.third = result;
        return result;
    });
}
function fourthQuery(allResult = {}) {
    return doTheQuery(allRessult.first, allResult.second)
    .then(result => {
        allResult.fourth = result;
        return result;
    });
}

那么你可以写 use

firstQuery()
.then(secondQuery)
.then(thirdQuery)
.then(fourthQuery)
.then ...

最终结果将是一个对象,其中包含 {first, second, third, fourth} 属性中所有查询的值

当然,如果你只想要第四个查询结果

firstQuery()
.then(secondQuery)
.then(thirdQuery)
.then(fourthQuery)
.then(result => result.fourth)
.then ...

通常您应该将 promises 视为值和依赖项,而不是一种控制执行流程的方式。一个可靠的选择是像这样组织您的代码:

var firstResult = firstQuery();
var secondResult = firstResult.then(secondQuery);
var thirdResult = secondResult.then(thirdQuery);
var fourthResult = Promise.join(firstResult, secondResult, fourthQuery);

基本上我想这里的关键是了解 bluebird 库的 join 方法(其他方法可以用于相同的效果),但另一个好处是我发现这种代码很多比混合原始变量和承诺变量更不容易出错。

另请注意,这是可能的,因为多次调用 then 同一承诺完全没问题。