以干净的方式打破javascript承诺链

use*_*275 10 javascript promise

我试图链接承诺,以便如果一个承诺被拒绝,链将破裂.我跟随前一个SO问题的线索并尝试将其应用于本机承诺,但我认为我误解了事情的运作方式.

以下是我重写代码的方法:

Promise.resolve()
    .then(function() {
        return step(1)
            .then(null, function() {
                stepError(1);
            });
    })
    .then(function() {
        return step(2)
            .then(null, function() {
                stepError(2);
            });
    })
    .then(function() {
        return step(3)
            .then(null, function() {
                stepError(3);
            });
    });

function step(n) {
    console.log('Step '+n);
    return (n === 2) ? Promise.reject(n) : Promise.resolve(n);
}

function stepError(n) {
    console.log('Error '+n);
    return Promise.reject(n);
}
Run Code Online (Sandbox Code Playgroud)

上面代码的输出是:

Step 1
Step 2
Error 2
Step 3
[UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): 2]
Run Code Online (Sandbox Code Playgroud)

根据我的理解,第2步应该打破链条,不应该执行第3步.当步骤(2)返回被拒绝的promise时,stepError(2)按预期执行.但是因为它返回Promise.reject(2),所以下一个函数不应该被执行,并且因为最后没有catch,所以步骤2的被拒绝的承诺似乎 - 正如预期的那样 - 被转发,直到它退出因为它没有找到任何处理程序链.

我在这里错过了什么?

这是一个可以玩的JSFiddle:https://jsfiddle.net/6p4t9xyk/

T.J*_*der 12

根据我的理解,第2步应该打破链条......

,但你不小心将拒绝转换为决议.

关于promises的关键是每次调用then都会创建一个新的 promise,它会根据then回调的内容进行解析/拒绝,而回调处理拒绝会将拒绝转换为解决方案,除非故意不这样做.

所以在这里:

return step(2)
    .then(null, function() {  // This handler converts the
        stepError(2);         // rejection into a resolution
    });                       // with the value `undefined`
Run Code Online (Sandbox Code Playgroud)

这样你就可以有错误处理程序来补偿错误.

由于stepError返回拒绝,您可以通过添加以下内容继续拒绝return:

return step(2)
    .then(null, function() {
        return stepError(2);  // Added `return`
    });
Run Code Online (Sandbox Code Playgroud)

...或者,完全删除该处理程序:

return step(2);
Run Code Online (Sandbox Code Playgroud)

...或者你可以throw在回调中自动变成拒绝.

未处理的拒绝警告是由没有消耗拒绝的事实引起的stepError.


这是返回结果的示例stepError:

Promise.resolve()
    .then(function() {
        return step(1)
            .then(null, function() {
                return stepError(1); // Added `return`
            });
    })
    .then(function() {
        return step(2)
            .then(null, function() {
                return stepError(2); // Added `return`
            });
    })
    .then(function() {
        return step(3)
            .then(null, function() {
                return stepError(3); // Added `return`
            });
    });

function step(n) {
    console.log('Step '+n);
    return (n === 2) ? Promise.reject(n) : Promise.resolve(n);
}

function stepError(n) {
    console.log('Error '+n);
    return Promise.reject(n);
}
Run Code Online (Sandbox Code Playgroud)