【问题标题】:Jquery Deferred Not reaching last .thenJquery Deferred 没有到达最后一个.then
【发布时间】:2015-12-31 16:57:26
【问题描述】:

我有一系列必须执行的函数。除了最后一个之外,它们都按顺序执行。 d1 执行,d2 执行,d3 执行,然后 done 函数中的代码在 d4 解析之前执行。想不通为什么。任何帮助将不胜感激。

$(document).ready(function() {
    var d1 = functiond1();
    var d2 = functiond2();
    var d3 = functiond3();
    var d4 = functiond4();

    d1.then(d2).then(d3).then(d4).done(function() {

    //Code here does not wait for d4 to end before executing
    //HELP! 

    });
});

function functiond1() {
    var dfd = $.Deferred();

    //Do stuff here
    //Works in sequence

    dfd.resolve();
    return dfd.promise();
}


function functiond2() {

    var dfd = $.Deferred();
    params = jQuery.param({
        'parm1': 1,
        'parm2': 2,
        'parm3': 3
    });


    jQuery.getJSON($.webMethoJSONGet1, params).done(function(data) {

        //Do stuff here
        //Works in sequence

        dfd.resolve();

    });

    return dfd.promise();
}

function functiond3() {
    var dfd = $.Deferred();

    //Do stuff here
    //Works in sequence

    dfd.resolve();
    return dfd.promise();
}

function functiond4() {

    var dfd = $.Deferred();

    params = jQuery.param({
        'parm1': 1,
        'parm2': 2,
        'parm3': 3
    });

    jQuery.getJSON($.webMethoJSONGet2, params).done(function(data) {

        //Do stuff here
        //does not work in sequence

        dfd.resolve();

    });

    return dfd.promise();
}

【问题讨论】:

  • 寻求帮助时,请以可读的方式缩进您的代码。我已经通过 jsbeautifier 为你运行了代码。
  • 很棒的提示。按要求完成。关于代码的任何提示?
  • 为什么到目前为止所有代码都缩进了?我已经为你修好了,现在更多的东西偏向右边而不是必要的。我已经重新修好了。
  • 延迟链进入 $(document).ready()。这是最后一次修复'。
  • 不,你没有。您的 getJson.done() 返回一个承诺,应该是您的函数返回的内容。在其中嵌套另一个 Promise 完全违背了使用 Promise 的目的。

标签: javascript jquery promise deferred


【解决方案1】:

很难说你想用这些承诺做什么。您首先调用所有 4 个函数,然后尝试使用一堆 then 回调将它们链接起来。如果您想将它们按顺序链接在一起,则应如下所示:

functiond1()
.then(functiond2)
.then(functiond3)
.then(functiond4)
.done(function() { /* blah */ });

如果你只想要一个结果,你可以使用$.when

$.when(functiond1(), functiond2(), functiond3(), functiond4())
.then(function(resultd1, resultd2, resultd3, resultd4) { /* blah */ });

另一方面,在您的函数中,您创建的 Promise 会在另一个不必要的 Promise 的 done 回调中解析。 $.getJSON.done() 调用本身返回一个承诺,因此不需要额外的承诺。只需返回从done() 返回的承诺。

抱歉,我对 jQuery 延迟对象并没有搞砸太多,但它们看起来与标准 Promises 足够相似。

【讨论】:

  • 不,这是错误的 - 你必须将函数引用传递给.then,而不是立即调用该函数的结果
  • @Alnitak 我将其修复为延迟调用 then 中的函数。谢谢。
  • 是的,我正在调用函数,每个函数都返回一个承诺,在前一个解决之前不应继续到下一个,但最后一个不会等到解决。
【解决方案2】:

要按顺序运行函数,您需要将引用传递给.then链中的函数,而不是调用这些函数的结果。 p>

例如

var d1 = functiond1;   // NB: no ()
...

d1.then(d2).then(d3).then(d4).done(...);    
functiond1().then(functiond2).then(functiond3).then(functiond4).done(...)

问题的最终原因是立即调用d4 将导致其已解决的承诺立即传递给.done,而不管.then 链的早期部分的状态如何。

你也不应该用额外的 Promise 包装你的 JSON 函数,因为 $.getJSON 已经返回了一个 Promise,如果 AJAX 查询失败,该 Promise 将被拒绝

function functiond4() {
    ...
    return $.getJSON(...);
}

【讨论】:

  • 感谢您的回答。不要注意函数名称。在发布问题以强调功能顺序之前,我将它们从原件中更改。相信这些不是我使用的名字。
【解决方案3】:

我在一个项目中遇到了同样的问题,这个带有数组的解决方案效果很好:

$(document).ready(function() {
    var pr = [];
    var d1 = functiond1();
    var d2 = functiond2();
    var d3 = functiond3();
    var d4 = functiond4();

    function functiond1() {
        var dfd = $.Deferred();
        pr.push(dfd);

        setTimeout(function(){
            $('body').append('1 resolved <br>');
            dfd.resolve();
        }, 2000);
    }


    function functiond2() {
        var dfd = $.Deferred();
        pr.push(dfd);

        params = jQuery.param({
            'parm1': 1,
            'parm2': 2,
            'parm3': 3
        });

        setTimeout(function(){
            $('body').append('2 resolved <br>');            
            dfd.resolve();
        }, 3000);
    }

    function functiond3() {
        var dfd = $.Deferred();
        pr.push(dfd);

        setTimeout(function(){
            $('body').append('3 resolved <br>');
            dfd.resolve();
        }, 1000);
    }

    function functiond4() {
        var dfd = $.Deferred();
        pr.push(dfd);

        params = jQuery.param({
            'parm1': 1,
            'parm2': 2,
            'parm3': 3
        });

        setTimeout(function(){
            $('body').append('4 resolved <br>');
            dfd.resolve();
        }, 50);
    }

    $.when.apply($, pr).then(function() {
        // do something
        $('body').append('proceed with code execution');
    });
});
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"&gt;&lt;/script&gt;

【讨论】:

  • 感谢您的回答。我正在验证。
  • 不客气,请分享您的代码,以防它不起作用。
  • 注意:这段代码将使所有四个函数同时运行,并行执行它们的异步操作,并且只有在它们全部完成后才解析。
  • 确实如此 - 我误读了。那么这实际上是他的问题
  • @Alnitak 使用这段代码,您可以完全实现 ricardo 想要的:-> 独立运行所有函数 -> 在 Promise 集合中注册它们 -> 一旦所有 Promise 得到解决,继续执行一些逻辑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
相关资源
最近更新 更多