如果并行函数已经失败,则阻止函数运行(使用jQuery $ .when())

时间:2014-07-18 14:45:58

标签: javascript jquery jquery-deferred

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

本质上我有两个并行的函数流,其次是在并行流完成时应该串行执行的函数。这是一个例子(它们是现实生活中的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()处理程序在出现任何错误时立即执行,链中的任何位置以及所有进一步执行都要停止。

大多数情况下,这是有效的 - 除了一个案例。如果在打蛋时出现故障,那么即使在这些任务开始之前已经发生故障,西红柿仍然会被清洗和切碎。同样,如果在洗西番茄时出现故障,这并不能阻止crackEggs和beatEggs功能运行。

您可以看到an example here

我对此的关注是,在我的现实代码中,我不希望浏览器对服务器进行AJAX调用,这可能会改变状态,如果没有意义,因为整个过程有已经失败了。

有没有办法做我想要的?我想我可以单独为每个并行任务附加失败处理程序,但我想知道是否有更简洁/重复的方式。

谢谢!

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

尝试(此模式)

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 http://jsfiddle.net/guest271314/WWF68/