attempting to break jQuery promise chain with .then, .fail and .reject

天涯浪子 提交于 2019-12-31 21:30:20

问题


Update: this issue was a result of jQuery 1.7 vs 1.8. Do not ever use promises in 1.7 beacuse they aren't chainable with returning a promise inside a .then. 1.8 looks like they didn't mess it up.

http://jsfiddle.net/delvarworld/28TDM/

// make a promise
var deferred = $.Deferred();
promise = deferred.promise();

// return a promise, that after 1 second, is rejected
promise.then(function(){
    var t = $.Deferred();
    setTimeout(function() {
        console.log('rejecting...');
        t.reject();
    }, 1000);

    return t.promise();
});

// if that promise is successful, do this
promise.then(function() {
    console.log('i should never be called');
})

// if it errors, do this
promise.fail(function() {
    console.log('i should be called');
});

deferred.resolve();

Expected: 'i should be called'

Actual: 'i should never be called'

Problem: I want to chain callbacks and have any one of them be able to break the chain and trigger the fail function, and skip the other chained callbacks. I don't understand why all of the thens are triggered and the fail is not triggered.

I'm coming from NodeJS's Q library, so I tried it with .then first. However, changing it to .pipe has no effect.


回答1:


You aren't re-defining the value of promise, try this:

http://jsfiddle.net/28TDM/1/

var deferred = $.Deferred();
promise = deferred.promise();

promise = promise.then(function(){
    var t = $.Deferred();
    setTimeout(function() {
        console.log('rejecting...');
        t.reject();
    }, 1000);

    return t.promise();
});

promise.then(function() {
    console.log('i should never be called');
})

promise.fail(function() {
    console.log('i should be called');
});

deferred.resolve();

Apparently it does work the way you thought it did, it just isn't documented https://api.jquery.com/deferred.then. Very cool. This is new functionality added in jQuery 1.8.0, more than likely they just aren't done updating the documentation.




回答2:


IMHO, you're not chaining anything. Your 2nd .then is attached to the same promise as that the first .then is attached to.

Why?

Notice that, then will always RETURN the new promise, rather than change the promise it being attached to. It doesn't have side effect.

For example:

var promiseX = promiseA
                 .then(function() { return promiseB; })
promiseX.then(function() { return promiseC; });

promiseA won't change its value after being attached then; it'll keep as is.

promiseX will be the return value of the 1st then, that is, promiseB.

So the 2nd then is actually attached to promiseB.

And this is exactly what @Kevin B did in his answer.


Another solution is, since .then will return the new promise, you can chain the .then functions like below.

var promiseX = promiseA
                 .then(function() { return promiseB; })
                 .then(function() { return promiseC; });

This time, the 1st then is attached to promiseA, and guess to which promise is the 2nd then being attached to?

You're right. It's promiseB, not promiseA. Because the 2nd then is actually being attached to the return value of the 1st then, i.e., promiseB.

And finally the 2nd then's return value is assigned to promiseX, so promiseX equals promiseC.

Ok, get back to the OP's question. The following code is my answer.

var deferred = $.Deferred();
promise = deferred.promise(); // this is the first promise

promise.then(function(){ // callbacks for 1st promise
    var t = $.Deferred();
    setTimeout(function() {
        console.log('rejecting...');
        t.reject();
    }, 1000);
    return t.promise(); // this is the 2nd promise
    // return $.Deferred().reject(); // To reject immediately.
}).then(function() { // callbacks for 2nd promise
    console.log('i should never be called');
}, function() {
    console.log('i should be called');
})

deferred.resolve();


来源:https://stackoverflow.com/questions/12149993/attempting-to-break-jquery-promise-chain-with-then-fail-and-reject

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!