尝试用.then,.fail和.reject打破jQuery承诺链

时间:2012-08-27 21:41:10

标签: jquery deferred chain promise

更新:此问题是jQuery 1.7 vs 1.8的结果。不要在1.7中使用promises,因为它们在.then内返回一个承诺是不可链接的。 1.8看起来他们并没有弄乱它。

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();

预期:'我应该被称为'

实际:'我永远不应该被称为'

问题:我想链接回调并让其中任何一个能够打破链并触发fail函数,并跳过其他链式回调。我不明白为什么所有的游戏都被触发而且未触发失败。

我来自NodeJS的Q库,所以我首先尝试使用.then。但是,将其更改为.pipe无效。

2 个答案:

答案 0 :(得分:11)

您没有重新定义promise的值,请尝试以下操作:

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();

显然确实以您认为的方式工作,它没有记录 https://api.jquery.com/deferred.then。很酷。这是jQuery 1.8.0中添加的新功能,很可能他们只是没有更新文档。

答案 1 :(得分:0)

恕我直言,你不是在串链。 您的第二个.then附加了第一个.then附加到的承诺。

为什么?

请注意,then将始终返回新承诺,而不是更改其附加的承诺。它没有副作用。

例如:

var promiseX = promiseA
                 .then(function() { return promiseB; })
promiseX.then(function() { return promiseC; });
附加promiseA后,

then 不会更改其值;它将保持原样。

promiseX将是第一个then的返回值,即promiseB

因此,第二个then实际上已附加到promiseB

这正是@Kevin B在答案中所做的。

另一种解决方案是,由于.then将返回新的承诺,您可以链接.then函数,如下所示。

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

这次,第一个then附加到promiseA,并猜测哪个承诺是附加的第二个then

你是对的。它是promiseB,而不是promiseA。因为第二个then实际上附加到第一个then的返回值,即promiseB

最后,第二个then的返回值已分配给promiseX,因此promiseX等于promiseC

好的,回到OP的问题。以下代码是我的答案。

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();