蓝鸟:等待一个承诺解决

时间:2015-04-19 09:22:46

标签: node.js promise bluebird

冒着听起来很愚蠢的风险:等待一个承诺解决的最有效方法是什么?说我有承诺A,我想创造承诺B. B的履行不依赖于A的最终价值。即使A被拒绝,也应该继续。然而,该过程不应该开始,直到A以这种或那种方式结算。

我目前的情况如下:

var prevResult;

function doStuff() {
    if (prevResult) {
        prevResult = promise.settle([ prevResult ]).then(function() {
            return doStuff();
        })
    } else {
        prevResult = updateDB().finally(function() {
            prevResult = null;
        });
    }
    return prevResult;
}

代码有点不明显。我也有点担心将一堆承诺链接在一起,看看它是如何起到减少琐碎协调的作用。似乎应该有一种更简单的方法。

4 个答案:

答案 0 :(得分:3)

最近,.reflect被引入作为更灵活的.settle和更好的抽象。您的用例听起来像.reflect

很容易
A.reflect().then(function(){
   return doSomethingThatReturnsB();
});

代码的完整示例:

var prevResult;
function doStuff() {
    prevResult = Promise.resolve(prevResult).reflect().then(function(){
        return updateDB();
    });
    return prevResult;
}

答案 1 :(得分:0)

您可以使用最终,无论先前承诺的结果如何,都会触发。

以下代码来自bluebird github doco。

function ajaxGetAsync(url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest;
        xhr.addEventListener("error", reject);
        xhr.addEventListener("load", resolve);
        xhr.open("GET", url);
        xhr.send(null);
    }).finally(function() {
        $("#ajax-loader-animation").hide();
    });
}

答案 2 :(得分:0)

假设您有两个承诺返回函数doAsync_AdoAsync_B

以下表达式将执行doAsync_A,等待其承诺结算(成为履行或被拒绝),然后执行doAsync_B

Promise.settle([doAsync_A()]).then(doAsync_B);

doAsync_B将通过" PromiseInspection"数组(这里是单个元素)。如有必要,您可以测试doAsync_A是成功还是失败。

function doAsync_B(results) {
    var r = results[0];
    if (r.isFulfilled()) {  // check if was successful
        console.log(r.value()); // the promise's return value
    } else if (r.isRejected()) { // check if the read failed
        console.log(r.reason()); // the promise's rejection reason
    }
}

改编自bluebird documentation

答案 3 :(得分:0)

我认为最好的方法是将doStuff作为履行和拒绝处理程序:

prevResult = prevResult.then(function() { return doStuff(); },
                             function() { return doStuff(); });

或者

prevResult = prevResult.catch(ignore).then(function() { return doStuff(); });

您似乎正在尝试排队updateDB次操作。我建议不要将prevResult重置为null,而是将其作为所有排队操作完成后履行的承诺。看看this example

相关问题