有没有办法在处理错误时像嵌套承诺一样链接承诺?

Is there any way to chain promises while handling errors as if promises were nested?

我有以下代码 (http://jsfiddle.net/tj1eo86s/):

promise(1).then(function() {
    console.log("OK1");
    promise(2).then(function() {
        console.log("OK2");
        promise(3).then(function() {
            console.log("OK3");
        }, function() {
            console.log("KO3");
        });
    }, function() {
        console.log("KO2");
    });
}, function() {
    console.log("KO1");
});

如果 promise(2) 被拒绝,输出将是:

OK1
KO2

如何在链接承诺时获得相同的行为?

我试过 (http://jsfiddle.net/7goh0ds9/):

promise(1)
.then(function() {
    console.log("OK1");
    return promise(2);
}, function() {
    console.log("KO1");
})
.then(function() {
    console.log("OK2");
    return promise(3);
}, function() {
    console.log("KO2");
})
.then(function() {
    console.log("OK3");
}, function() {
    console.log("KO3");
});

但输出是:

OK1
KO2
OK3

然后我尝试在错误回调中抛出错误(http://jsfiddle.net/cyx6mohy/):

promise(1)
.then(function() {
    console.log("OK1");
    return promise(2);
}, function() {
    console.log("KO1");
    throw "KO1";
})
.then(function() {
    console.log("OK2");
    return promise(3);
}, function() {
    console.log("KO2");
    throw "KO2";
})
.then(function() {
    console.log("OK3");
}, function() {
    console.log("KO3");
    throw "KO3";
});

但现在我有:

OK1
KO2
KO3

我实际上理解所有这些行为,但我一直无法找到像嵌套承诺一样处理错误的解决方案。

您可以使用索引作为参数拒绝,然后添加一个 .catch 并在那里处理错误:

var breakOnPromise = 2;

function promise(i) {
    return new Promise(function(resolve, reject) {
        if (i == breakOnPromise) {
            reject(i); // pass index to catch
        } else {
            resolve();
        }
    });
}

promise(1).then(function() {
    console.log("OK1");
    return promise(2);
}).then(function() {
    console.log("OK2");
    return promise(3);
}).then(function() {
    console.log("OK3");
}).catch(function(i) {
    // This is just for your case,
    // but you could use an `if` statement
    var err = ["KO1", "KO2", "KO3"][i - 1];
    console.log(err);
});

如果您的问题是如何以与任意嵌套完全相同的方式一般地使链接处理错误,答案是您不能以一般方式。链接是一种与任意嵌套根本不同的控制结构。

您可以设计一个与链接具有基本相同行为的嵌套。或者,如果您想在链式世界中模拟来自嵌套结构的特定错误处理行为,您 "might" 能够在链式序列中使用适当的错误处理和控制流来实现这一点。请注意,我说 "might" 是因为它完全取决于嵌套序列在做什么。您也可能无法使用纯链接来模拟它。

如果你的问题是当链中的这个特定承诺被拒绝时,我如何让这个链式承诺序列生成这个特定响应,那么这可能是可能的,但它会根据你的特定情况和期望的结果进行编码,不是以某种通用的方式。

基本上,有使用链接的理由,有使用嵌套的理由,也有理由结合使用两者。像你一样,我更喜欢链接,因为控制流和可读性​​看起来更简单,所以我总是从这种结构开始,但在我的代码中肯定有很多时候我必须对操作的某些部分使用嵌套(通常是因为分支决策或某些类型的所需错误处理)。