如果其中一个延期被拒绝,为什么主人不会在$。提前被拒绝?

时间:2014-05-30 09:56:43

标签: javascript jquery jquery-deferred

根据http://api.jquery.com/jquery.when/ $.when()拒绝其中一个延期被拒绝的主延期。为什么我在获取OnPreRenderFailed'之前获得所有4个console.log消息。消息。
我的理解是,一旦第二次延期被拒绝,我就不应该console.log('third deferred');console.log('fourth deferred');或在console.log('caught OnPreRenderFailed');之后获得它们 除非我是超级幸运(或不是)让方法始终以(1,3,4,2)顺序发射。我必须在这里遗漏一些东西  JSFiddle

 $(document).on('OnPreRenderResolved', function () {
       console.log('caught OnPreRenderResolved');
   });
   $(document).on('OnPreRenderFailed', function () {
       console.log('caught OnPreRenderFailed');
   })
    $(document).on('OnPreRender', function (e, options) {
       console.log('OnPreRender fired');
       options.callback();
   });
   $(document).trigger('OnPreRender', {
       callback: function () {
           $.when.apply($, [$.Deferred(function (deferred) {
               console.log('first deferred');
               deferred.resolve();
           }), $.Deferred(function (deferred) {
               console.log('second deferred');
               deferred.reject();
           }), $.Deferred(function (deferred) {
               console.log('third deferred');
               deferred.resolve();
           }), $.Deferred(function (deferred) {
               console.log('fourth deferred');
               deferred.resolve();
           })]).then(function () {
               $(document).trigger("OnPreRenderResolved");
           }, function () {
               $(document).trigger("OnPreRenderFailed");
           })
       }
   });

3 个答案:

答案 0 :(得分:2)

问题是评估始终是同步的。你不能强迫两者之间的任何东西。所以为了做到这一点,你必须强制你的函数异步。您可以使用setTimeout(..., 0);

来实现此目的
$.when.apply($, [
    $.Deferred(function (deferred) {
        setTimeout(function() {
            console.log('first deferred');
            deferred.resolve();
        }, 0);
    }),
    $.Deferred(function (deferred) {
        setTimeout(function() {
            console.log('second deferred');
            deferred.resolve();
        }, 0);
    }),
    ...
]);

不要将$.when与同步代码一起使用。这简直毫无意义。

但请注意,未定义setTimeout的顺序。你可能会得到奇怪的结果。

答案 1 :(得分:1)

这种情况正在发生,因为JS解释器必须先评估传递给$.when的参数才能真正调用$.when

由于对$.Deferred的调用都是内联参数,因此它们都会完成(输出他们的console.log消息),但只有在完成后才会$.when继续进行,{指出它将确定其中一个承诺被拒绝。

就像你写的那样:

f(a(), b(), c(), d());

每个a ... d必须在f被调用之前返回。

此外,由于您的任何一个函数都没有启动任何异步操作,因此在调用$.when之后,调用之后出现的控制台输出绝对没有机会。

答案 2 :(得分:0)

不完全,什么时候仍然被拒绝但是其他异步进程没有停止,什么时候会在第一个无法解决时立即报告拒绝。我见过的唯一能够取消承诺的图书馆是蓝鸟