如果一个并行函数已经失败,阻止该函数继续运行(使用jQuery $.when())

Preventing a function from running if a parallel function has already failed (using jQuery $.when())

本文关键字:函数 运行 继续 jQuery when 使用 失败 一个 并行 如果      更新时间:2023-09-26

我有一个相当复杂的异步函数系列,我在jQuery deferred的帮助下链接它们。

实际上我有两个并行的函数流,后面跟着应该在并行流完成后串行执行的函数。下面是一个示例(它们是现实生活中的AJAX调用):

function makeOmelette() {
    $.when(
        crackEggs().then(beatEggs),
        washTomatos().then(chopTomatos)
    ).then(mixEggsAndTomatos).then(fryEggsAndTomatos).done(function() {
        msg('Omelette is ready!');
    }).fail(function() {
        msg('Oh no, omelette fail!');
    });
}

最后的done()fail()处理程序处理成功或失败。我希望fail()处理程序执行一旦出现任何问题,在链的任何地方,并为所有进一步的执行停止。

大多数情况下,这是有效的——除了一种情况。如果打蛋失败了,那么西红柿仍然要清洗和切碎——即使在这些任务中的任何一个开始时已经发生了失败。同样,如果洗番茄失败,也不会阻止crackegg和beatEggs函数的运行。

你可以在这里看到一个例子。

我对此的担忧是,在我的实际代码中,我不希望浏览器向服务器发出AJAX调用,如果由于整个过程已经失败而没有意义,那么这可能会潜在地改变状态。

有办法做我想做的吗?我想我可以为每个并行任务单独附加失败处理程序,但我想知道是否有一种不那么冗长/重复的方法。

谢谢!

为状态添加一个变量。例如在done( var status = 1 )fail( var status = 2内部,然后在运行并行函数之前放一个简单的语句,以便它不会运行status = 2

Try (this pattern)

html

<input type="button" value="reject" />
<input type="button" value="resolve" /> <output></output> <output></output>
<div id="messages"></div>

js

$(function () {
    $("input").on("click", function (e) {
        var dfd = new $.Deferred();
        $("#messages").children().remove();
        makeOmelette(this.value);
        function makeOmelette(resolveReject, dfd) {
            // dfd = dfd;
            $.when(
            // `crackEggs("resolve")`, `crackEggs("reject")`
            crackEggs(resolveReject), 
            washTomatos())
                .done(function (a, b) {
                if (a === "rejected") {
                    err();
                };
                if (a === "resolved") {
                    beatEggs();
                    chopTomatos();
                    mixEggsAndTomatos();
                    fryEggsAndTomatos();
                    success();
                };
            });
        };
        function success() {
            dfd.done(function (s) {
                msg('Omelette is ready!');
                $("output:first").val(s);
            })
        };
        function err() {
            dfd.fail(function (e) {
                msg('Oh no, omelette fail!');
                $("output:first").val(e);
            });
        };
        dfd.always(function () {
            $("output:last").val(dfd.state() + " at " + $.now())
        });
        function crackEggs(_resolveReject) {
            (_resolveReject === "reject" 
             ? dfd.reject(_resolveReject + " called at " + $.now()) 
             : dfd.resolve(_resolveReject + " called at " + $.now())
            );
            msg('Cracking eggs');
            return dfd.state();
        }
        function beatEggs() {
            msg('Beating eggs');
            return dfd.state();
        }
        function washTomatos() {
            msg('Washing tomatos');
            return dfd.state();
        }
        function chopTomatos() {
            msg('Chopping tomatos');
            return dfd.state();
        }
        function mixEggsAndTomatos() {
            msg('Mixing eggs and tomatos');
            return dfd.state();
        }
        function fryEggsAndTomatos() {
            msg('Frying eggs and tomatos');
            return dfd.state();
        }
        function msg(text) {
            $('#messages').append('<p>' + text + '</p>');
        }
    });
});

JSFiddle https://jsfiddle.net/guest271314/WWF68/