jQuery $ .when-有什么方法可以阻止.fail提前触发?

时间:2018-08-16 17:11:15

标签: javascript jquery promise

根据jQuery文档$ .when,如果任何一个参数promise都失败了,那么.when将不再等待,并且将立即失败。它也不会取消其他承诺。

是否有一种方法可以强制$ .when实际等待其所有承诺都已完成?另外,我可以/应该使用其他方法吗?

也许是使用错误工具的情况,但是我试图阻止UI(加载微调器),同时获取2个部分的数据。我可以独立处理两个部分的失败。当(且仅当)所有承诺都完成(成功或失败)时,我才想取消阻止页面。

在下面的示例代码中,“ callSvc”是一种测试方法,该方法采用字符串“服务”标识符,以毫秒为单位的服务器睡眠状态以及指示Web调用是否失败的指示器。

callSvc("sync", 0, false)
    .then(function (result) {
        return $.when(
            callSvc("ebill", 4000, false)
                .then(function (a, b, c, d) {
                    debugger;   
                }),
            callSvc("epol", 2000, true)
                .done(function () {
                    // set up epol section with data
                    debugger;
                })
                .fail(function () {
                    // set up epol section for failure
                    debugger;
                })
        ).done(function (ebill, epol) {
            // just here to test ways to stop early-fail
            debugger;
        }).fail(function () {
            // just here to test ways to stop early-fail
            debugger;
        })
    }).fail(function (err) {
        // show message
        debugger;   
    }).always(function () {
        // unblock the screen
        debugger;
    });

2 个答案:

答案 0 :(得分:1)

对于多参数$.when()Promise.all而言,只要任何调用失败,该规范就会失败。但是,使用小型包装方法,您可以将失败变成(临时)成功。这等效于调用catch,但使用两个参数then代替:

function wrapWithSuccessFlag(promise) {
  return promise.then(
      successfulValue => { return { success: true, value: successfulValue }; },
      failureReason => { return { success: false, reason: failureReason }; });
}

callSvc("sync", 0, false).then(result => {
    return $.when(
        wrapWithSuccessFlag(callSvc("ebill", 4000, false)
            .then(function (a, b, c, d) {
                debugger;   
            })),
        wrapWithSuccessFlag(callSvc("epol", 2000, true)
            .done(function () {
                // set up epol section with data
                debugger;
            })
            .fail(function () {
                // set up epol section for failure
                debugger;
            }))
    ).done(function (ebill, epol) {
        // Determine whether ebill and epol succeeded or failed.
        // You can also throw an error here using ebill or epol's reason,
        // which gets you the error handling you're used to.
    });

答案 1 :(得分:0)

好吧,答案似乎是。相反,我不得不手动管理自己的承诺/延期。

这是我最终使用的代码模式:

var callSvc = function (svcName, sleep, shouldFail) {
    return $.ajax{...};
}

callSvc("sync", 0, true)
    .then(function (result) {

        var ebillPromise = $.Deferred();
        var epolPromise = $.Deferred();

        callSvc("ebill", 4000, false)
            .then(function (data) {
                // ebill success
                debugger;
                ebillPromise.resolve();
            }, function () {
                // ebill fail
                debugger;
                ebillPromise.resolve();
            });
        callSvc("epol", 2000, true)
            .then(function (data) {
                // epol success
                debugger;
                epolPromise.resolve();
            }, function () {
                // epol fail
                debugger;
                epolPromise.resolve();
            });

        return $.when(
            ebillPromise,
            epolPromise
        )
    }).fail(function () {
        debugger;
    }).always(function () {
        // unblock the screen
        debugger;
    });

之所以有效,是因为我的承诺从未被“拒绝”,所以我的$ .when()将等待。

但是,如果我们可以告诉JQuery等待,那肯定会很好。也许是“ $ .reallyWait()”函数...? :)

感谢@JeffBowman和@bhmahler让我指出正确的方向!