jQuery Deferred.then - failFilter 参数

jQuery Deferred.then - failFilter argument

我正在努力解决 jQuery deferred/promises(使用 v1.8+)。

通过阅读文档,一个 $.Deferred.then(...) 方法接受一个 doneFilter 和一个 failFilter 作为执行的参数,它 return 是一个承诺,我们可以使用它链接如下:

function doDefer() {
    var $defer = $.Deferred();

    doSomethingAsynchronous(
        function () {
            $defer.resolve();
        },
        function () {
            $defer.reject();
        }
    );

    return $defer.promise();
}

doDefer()
    .then(function () {
        return;
    }, function () {
        // second `then` not called
    })
    .then(function (b) {
        // `b` is undefined, since first `then` returned without a value.
    }, function () {
        // fail end
    });

两个问题:

  1. 为什么执行链在 doDefer() 中停止,如果它命中第一个 fail 函数?据我了解,then return 是一个 $.Deferred.promise(),这就是第二个 then 函数被链接(和执行)的方式。第一个链中的 then doneFilter/function/callback 总是返回(?) - 所以 why/how 是否 jQuery 以不同方式处理 failFilter
  2. 为什么 then return 一个 $.Deferred.promise(), 而 done/always/fail, 等等 return $.Deferred?这有什么用(为什么它与 then 不同)?

你可以看到这个例子,它的工作正常:

function doDefer() {
    var $defer = $.Deferred();

    setTimeout( function(){
                doSomethingAsynchronous(
                    function ( value ) {
                        // func1 - value is a random number
                        $defer.resolve( value );
                    },
                    function () {
                        $defer.reject();
                    }
                );
            }, 1000 );

    return $defer.promise();
}

function doSomethingAsynchronous( func1, func2 ){
    // random number 0-10
    var random = Math.round( Math.random()*10 )
    if( random > 5 ){
        return func1.call( this, random );
    }else{
        return func2.call( this );
    }
}

doDefer().then(function ( value ) {
    // success
    // make double of random
    return value*2;
}, function () {
    // fail when random number < 5
})
.then(function (b) {
    // `b` is double of random number
    console.log(b);
}, function () {
    // fail end
});

希望对你有所帮助

Why does execution chain stop in doDefer(), if it hits the first fail function? As I understand, then returns a promise which is how the second then function is chained (and executes). The then done callback in the first chain always returs(?) - so why/how does jQuery handle the failFilter differently?

我不确定我是否理解正确,但有两件事你应该知道:

  • then(done, fail) 只会执行其回调之一,具体取决于它们所链接的承诺是已实现还是已拒绝。
  • error handling is completely broken in jQuery. The callback does get called as expected, but the promise returned by the .then(…) call does not behave Promises/A+ compliant. Wait for jQuery 3.0, use a proper promise library (),或者学会忍受它。

Why does then return a $.Deferred.promise()

因为这是一个将根据相应回调的结果解决的承诺。这不是你可以自己解决的延迟。另见 What are the differences between Deferred, Promise and Future in JavaScript?

…yet done/always/fail, etc. return a $.Deferred?

他们没有。他们只是 return 他们被调用的对象,无论它是承诺还是延迟。

failHandler 会像你说的那样停止执行。关键是看链条。失败处理程序只有在其链接的 Promise 被拒绝时才会执行。确保您将链中的每个 link 视为一个单独的承诺。

链接可以重写如下。

dfd1 = doDefer();

dfd2 = dfd1.then( success1, fail1 );

dfd3 = dfd2.then( success2, fail2 );

在这个例子中,success1 只有在 dfd1 被解析时才会被调用。如果被拒绝,将调用 fail1 并且链将停止。

同样,只有在 dfd2 被解析时才会调用 success2(换句话说,success1 returns 一个值或解析一个返回的承诺)。执行 fail2 的唯一方法是 dfd2success1 明确拒绝(错误冒泡在 jQuery 的实现中不起作用)。

tl;dr - 失败不要链接,正如@Bergi 所说,错误处理在 jQuery

中被破坏