6

Re: https://github.com/tildeio/rsvp.js

I have a function called doSomething() that does something for a little while and then returns an RSVP.Promise. Then, a chain of success and failure callbacks are registered with the returned promise (see code below). The behavior I expected was, if the promise is fulfilled, the chain of success callbacks registered with the promise will be fired, and if the promise is rejected (fails), the chain of failure callbacks will be fired.

I get the expected behavior for when the promise is fulfilled, but I get a behavior different than what I expected when the promise is rejected. That is, the success callbacks are chained and output of one success callback is passed on to the next success callback in the chain. But it appears the failure callbacks are not chained. They behave almost like the catch in a try/catch block (see code and output below).

Can someone explain this behavior? Is this really the way it's suppose to work, or is this an error in the way rsvp.js handles a rejected/failed promise that has a chain of failure callbacks registered with it? I'm reading the Promises/A+ spec now to try and figure this out, but if someone knows this stuff off the top of their head, would love to hear your explanation. Thanks in advance.

jsfiddle: http://jsfiddle.net/rylie/VYSj7/2/

doSomething()  // returns an RSVP.Promise object
    .then(
        function(message) { console.log("then success 1: " + message); return "from success 1"; },  // success callback
        function(message) { console.log("then failure 1: " + message); return "from failure 1"; }   // failure callback
    )
    .then(
        function(message) { console.log("then success 2: " + message); return "from success 2"; },  // success callback
        function(message) { console.log("then failure 2: " + message); return "from failure 2"; }   // failure callback
    )
    .then(
        function(message) { console.log("then success 3: " + message); return "from success 3"; }   // success callback
    )
    .then(
        null,
        function(message) { console.log("then failure 4: " + message); return "from failure 4"; }   // failure callback
    )
    .then(
        function(message) { console.log("then success 5: " + message); return "from success 5"; },  // success callback
        function(message) { console.log("then failure 5: " + message); return "from failure 5"; }   // failure callback
    );

** When the promise is fulfilled (succeeds), this is the output I get and expected:

then success 1: Promise fulfilled!
then success 2: from success 1
then success 3: from success 2
then success 5: from success 3 

** When the promise is rejected (fails), this is the output I get:

then failure 1: Promise rejected!
then success 2: from failure 1
then success 3: from success 2
then success 5: from success 3 

** This is what I expected (on a rejected/failed promise):

then failure 1: Promise rejected!
then failure 2: from failure 1
then failure 4: from failure 2
then failure 5: from failure 4    
4

1 回答 1

12

您应该忘记.then()甚至需要超过 1 个参数并使用该.catch方法,它会更有意义。

Promise 提供了与一些同步代码结构的对应关系,但是当你只有一个低级的.then(). 您正在寻找的基本上是一组回调/回调聚合,但这根本不是承诺的重点。

认为.catch(fn)相同.then(null, fn)

doSomething().then(function(val) {
    console.log(val);
}).catch(function(e) {
    console.error(e);
});

并行同步代码(想象doSomething同步返回):

try {
    var val = doSomething();
    console.log(val);
}
catch(e) {
    console.error(e);
}

多个捕获(请记住,这.catch是更具可读性的别名.then(null, fn)

doSomething().then(function(val) {
    console.log(val);
}).catch(function(e) {
    return e;
}).catch(function(e){
    //Will not get here ever
    //because error thrown from doSomething()
    //was handled in the upper catch which doesn't trow
});

平行线:

try {
    try {
        var val = doSomething();
        console.log(val);
    }
    catch(e) {
        //no need for explicit return e
    }
}
catch( e ) {
    //Will not get here ever
    //because error thrown from doSomething()
    //was handled in the upper catch which doesn't trow
}

所以现在你应该注意到你可以通过抛出而不是返回来创建预期的结果http://jsfiddle.net/VYSj7/3/

.catch()IMO 是 Promise 库提供的基本方法,并且将来也将包含在内置的 Javascript Promise 中。但是,如果没有提供这样的方法,你可以(或者应该是,不幸的是有些实现不使用原型):

Promise.prototype.catch = function(fn) {
    return this.then(null, fn);
};

另见拒绝变成满足

于 2013-11-01T13:44:35.657 回答