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

问题描述 投票:0回答:2

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

有没有办法强制 $.when 真正等到它的所有承诺都完成?或者,我可以/应该使用其他方法吗?

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

在下面的示例代码中,“callSvc”是一个测试方法,它采用字符串“service”标识符、以毫秒为单位的服务器睡眠时间以及网络调用是否失败的指示符。

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;
    });
javascript jquery promise
2个回答
2
投票

对于多参数

$.when()
Promise.all
,一旦任何调用失败,规范就会失败。
Promise.allSettled
,在回答此问题后于 2019-2020 年引入,具有非常相似的行为,您可以使用它。

使用一个小的包装方法,您可以以与

Promise.allSettled
类似的方式将失败转变为(暂时)成功。这相当于调用
catch
,但使用两个参数
then
调用:

function wrapWithSuccessFlag(promise) {
  return promise.then(
      successfulValue => { return { status: 'fulfilled', value: successfulValue }; },
      failureReason => { return { status: 'rejected', 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.
    });

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 让我指明了正确的方向!

© www.soinside.com 2019 - 2024. All rights reserved.