链接Javascript的承诺

我试图从MDN文档中了解Promises。 第一个例子演示了thencatch方法:

// We define what to do when the promise is resolved/fulfilled with the then() call,
// and the catch() method defines what to do if the promise is rejected.
p1.then(
    // Log the fulfillment value
    function(val) {
        log.insertAdjacentHTML('beforeend', val +
            ') Promise fulfilled (<small>Async code terminated</small>)<br/>');
    })
.catch(
    // Log the rejection reason
    function(reason) {
        console.log('Handle rejected promise ('+reason+') here.');
    });

该文件指出, then方法返回一个新的承诺,所以不要等同于上面的代码

var p2 = p1.then(
    // Log the fulfillment value
    function(val) {
        log.insertAdjacentHTML('beforeend', val +
            ') Promise fulfilled (<small>Async code terminated</small>)<br/>');
    });
p2.catch(
    // Log the rejection reason
    function(reason) {
        console.log('Handle rejected promise ('+reason+') here.');
    });

如果是这样,那么这是否意味着只有在p1.then返回的承诺而不是承诺p1决定拒绝的情况下才会调用catch回调p1.then ? 我不需要这样做:

p1.then( /* etc. */ );
// and for rejected resolutions
p1.catch( /* etc. */ );

搭上拒绝承诺的p1 ,而不是链接的的catchthen

起初,我认为从p1.then返回的诺言与p1相同,就像jQuery如何处理其大部分API一样。 但下面清楚地表明,这两个承诺是不同的。

var p1 = new Promise(function(resolve, reject) { 
  resolve("Success!");
});

console.log(p1);
// Promise { <state>: "fulfilled", <value>: "Success!" }

var p2 = p1.then(function(value) {
  console.log(value);
});
// Success!

console.log(p2); 
// Promise { <state>: "fulfilled", <value>: undefined }

另外,我用三种方法在JSFiddle中玩过:

  • p1.then(onFulfilled).catch(onRejected);
  • p1.then(onFulfilled); p1.catch(onRejected);
  • p1.then(onFulfilled, onRejected);
  • 所有三个工作。 我可以理解后两者。 我的问题的要点是,为什么第一种方法也有效?


    首先,关于承诺的相关部分如何工作的一点背景:

    p1.then(...)确实会返回一个链接到前一个链接的新承诺。 所以, p1.then(...).then(...)只有在第一个完成后才会执行第二个.then()处理程序。 而且,如果第一个.then()处理程序返回未完成的承诺,那么它将等待返回的承诺解决此第二个承诺并调用第二个.then()处理程序之前解决。

    其次,当一个承诺链拒绝链中的任何地方时,它会立即跳过链(跳过任何满足的处理程序),直到它到达第一个拒绝处理程序(不管它是否从第二个参数的.catch().then() )。 这是承诺拒绝的一个非常重要的部分,因为这意味着您不必在承诺链的每个层面都被拒绝。 您可以将一个.catch()放在链的末尾,并且链中任何位置发生的任何拒绝都将直接转到.catch()

    另外,值得了解的是.catch(fn)只是.catch(fn) .then(null, fn)一个快捷方式。 它没有任何不同。

    此外,记住,(就像.then().catch()也将返回一个新的承诺。 如果.catch()处理程序本身不抛出或返回被拒绝的承诺,则拒绝将被视为“已处理”,并且返回的承诺将解析,从而允许该链继续从那里继续。 这允许你处理一个错误,然后有意识地决定你是否希望链继续正常的履行逻辑或保持拒绝。

    现在,针对您的具体问题...

    如果是这样,那么这是否意味着只有在p1.then返回的承诺而不是承诺p1决定拒绝的情况下才会调用catch回调函数? 我不需要这样做:

    否。 拒绝会立即传播到下一个拒绝处理程序,跳过所有解析处理程序。 所以,它会跳到下一个.catch()链。

    这是通过承诺使错误处理变得更加简单的事情之一。 您可以将.catch()放在链的末尾,它会从链中的任何位置捕获错误。

    有时候有理由在链的中间拦截错误(如果你想在错误中分支和更改逻辑,然后继续使用其他代码)或者如果你想“处理”错误并继续前进。 但是,如果你的链条全是或者没有,那么你可以在链尾放一个.catch()来捕捉所有的错误。

    它意味着与同步代码中的try / catch块相似。 将一个.catch()放在链的末尾就像在一堆同步代码的最高层放置一个try / catch块。 它会在代码中的任何地方捕获异常。

    所有三个工作。 我可以理解后两者。 我的问题的要点是,为什么第一种方法也有效?

    所有三个都差不多。 2和3是相同的。 实际上, .catch(fn)只不过是.catch(fn) .then(null, fn)的快捷方式。

    选项1略有不同,因为如果onFulfilled处理程序抛出或返回被拒绝的promise,那么.catch()处理程序将被调用。 在另外两种选择中,情况并非如此。 除了这一点之外,它的工作原理是一样的(如你所观察到的)。

    选项1的作用是因为拒绝传播到链中。 因此,如果p1拒绝,或者onFulfilled处理程序返回被拒绝的promise或抛出,则将.catch()处理程序。


    不应该代码是相等的

    他们是。

    如果是这样,那么这是否意味着只有在p1.then返回的承诺而不是承诺p1决定拒绝的情况下才会调用catch回调p1.then

    对,就是这样。

    但是,当p1拒绝时, p2也会这样做,因为您没有将onRejected处理程序传递给将截取它的onRejected .then()调用。 拒绝只是传播链条。

    我用三种方法在JSFiddle中玩过。 所有三个工作。

    他们这样做,但他们不这样做。

    p1.then(onFulfilled, onRejected);
    

    这是你通常会想要做的。

    p1.then(onFulfilled); p1.catch(onRejected);
    

    这最终会有两个不同的承诺,一个将通过onFulfilled结果解决或拒绝,另一个将通过onRejected结果实现或解决。

    p1.then(onFulfilled).catch(onRejected);
    

    那是与第一种不同的野兽,请看“什么时候。”(成功,失败)是否认为承诺的反模式?


    这个:

    var p2 = p1.then()
    p2.catch()
    

    与此相同:

    p1.then().catch()
    

    你也可以这样做:

    p1
     .then(response => response.body)
     .then(body => JSON.parse(body))
     .then(data => console.log(data))
     .catch(e => console.log('something somewhere failed'))
    
    链接地址: http://www.djcxy.com/p/55505.html

    上一篇: Chaining Javascript promises

    下一篇: Confuse about error and reject in Promise