【问题标题】:jQuery ajax and the "when" functionjQuery ajax 和“when”函数
【发布时间】:2012-11-12 12:53:54
【问题描述】:

我有一些(比如说 5 个)ajax 请求,我使用jQuery.ajax 函数同时运行。

现在我想同步和汇总他们的结果,我使用jQuery.when 函数来实现这一点。

我的问题是$.when 在其中一个请求失败后立即返回,并阻止其他请求即使成功也返回。

如何同步并从我的所有 ajax 请求中获取所有结果(那些失败的和那些成功的)?

【问题讨论】:

  • 如果您发布当前代码会有所帮助..

标签: jquery ajax promise


【解决方案1】:

工作演示:http://jsbin.com/ocawoj/4/edit

function waitForAllPromisesToFinish () {
    var i,
        responses = [],
        deferred = $.Deferred(),
        helpers = {
            addToResponses: function (index, data) {
                responses[index] = data;

                var i = 0,
                    isAnyNull = false;

                for (i = 0; i < responses.length; i++) {
                    if (responses[i] === null) {
                        isAnyNull = true;
                        break;
                    } 
                }

                if (isAnyNull === false) {
                    deferred.resolve(responses);
                }
            },
            setupPromise: function (promise, index) {
                promise.always(function () {
                    var args = Array.prototype.slice.call(arguments);
                    helpers.addToResponses(index, args);
                });
            }
        },
        ajaxPromises = Array.prototype.slice.call(arguments);

    for (i = 0; i < ajaxPromises.length; i++) {
        responses[i] = null;
    }

    for (i = 0; i < ajaxPromises.length; i++) {
        helpers.setupPromise(ajaxPromises[i], i);
    }

    return deferred.promise();
}

函数返回一个承诺。您附加了一个与您提供给 $.when() 的处理程序略有不同的完成处理程序。该函数跟踪每个 ajax 承诺的响应。每当它发现所有的 ajax Promise 都返回了数据,无论是成功还是失败,它都会解决这个 Promise。

可能有更有效的方法来实现相同的目标,尽管这是我首先想到的。

【讨论】:

  • 嗨!看来这正是我想要的!但老实说,我暗中希望有更“标准”的方式来做这件事,因为我认为我不是地球上第一个试图解决这类问题的人。无论如何,感谢您的回复和时间! :)
  • 我刚刚浏览了$.when 的代码,我所做的与$.when 所做的非常相似。不同之处在于$.when 调用deferred.reject 在任何延迟失败的那一刻。这确实是有道理的,否则你怎么知道是否有任何延期失败?您将需要检查每个延迟的响应,以确定它是成功响应还是失败响应。您可以在他们的错误跟踪器上提出这个问题,也许您可​​能会得到一些关于核心团队认为应该如何解决这个问题的反馈。
  • 我同意这不是一个错误,'$.when' 是这样工作的,它是有道理的,没关系。我认为,这只是缺少功能,因为在很多情况下,我们需要一种“whenAll”函数来同步所有结果,无论它们是否成功。我不得不说,我很惊讶没有开箱即用的功能或解决方法(我之前称之为“标准”方式)。
【解决方案2】:

您可以定义一个、两个或三个更新函数(取决于您想要做什么)来获取相应承诺(ajax 回调)的响应:

function bindPromises(updateSuccess, updateFail, updateAnyway) {
    var arrPromises = [];

    // automate the promise retrieval if you want, that's up to you.
    arrPromises[0] = ajaxRequest1();
    arrPromises[1] = ajaxRequest2();
    arrPromises[2] = ajaxRequest3();
    arrPromises[3] = ajaxRequest4();
    arrPromises[4] = ajaxRequest5();

    for(var j = 0; j < arrPromises.length; j++) {
        arrPromises[j].then( updateSuccess, updateFail, updateAnyway );
    }
}

或者,如果您想实现更多自动化:

function bindPromises(arrayOfAjaxCalls, updateSuccess, updateFail, updateAnyway) {
    var arrPromises = [];

    for(var i = 0; i < arrayOfAjaxCalls.length; i++) {
        arrPromises[i] = (arrayOfAjaxCalls[i])();
        arrPromises[i].then( updateSuccess, updateFail, updateAnyway );
    }
}

如果您不熟悉 Promises,我想向您推荐一篇涵盖该主题的精彩文章:Understanding jQuery.Deferred and Promise

【讨论】:

  • 嗨,如果我错了,请纠正我,但在我看来,您的代码为每个 ajax 响应执行每个回调,不是吗?我正在寻找的是一种解决方案,其中一个方法在所有请求完成后仅执行一次(无论它们是否都成功)。通过这种方法,我应该能够获得所有 ajax 调用响应(那些失败和成功的响应)。
  • 不,你是对的。但我不确定您是想等到所有通话结束,还是决定在每次通话结束后采取一些行动。显然你现在有两种方法的例子;)
猜你喜欢
  • 2016-09-25
  • 1970-01-01
  • 2016-06-10
  • 2012-11-05
  • 1970-01-01
  • 2013-05-14
  • 2020-01-09
  • 1970-01-01
  • 2015-06-19
相关资源
最近更新 更多