6

我想编写一个执行十几个异步 ajax 请求的函数,等待所有这些请求完成,然后返回聚合信息。喜欢:

function countHealthy(urls) {
  var healthy = 0;
  for (var i = 0; i < urls.length; ++i) {
    $.ajax({url: urls[i], async: true, id: i})
    .done(function (data) { ++healthy; });
  }
  // Wait for all ajax to finish.
  return healthy;
}

PS:++healthy 线程安全吗?

4

5 回答 5

6

Javascript 没有线程,所以线程安全不是问题。您的 return 语句是问题所在,它需要进入 ajax 调用在完成时执行的回调。由于 ajax 是异步发生的,正如您的代码所示,return 语句将在所有请求返回之前触发。

您可能想查看query deferreds,它似乎是为这类事情而生的。直接从那个链接

function doAjax() {
  return $.get('foo.htm');
}

function doMoreAjax() {
  return $.get('bar.htm');
}

$.when( doAjax(), doMoreAjax() )
  .done(function() {
    console.log( 'I fire once BOTH ajax requests have completed!' );
  })
  .fail(function() {
    console.log( 'I fire if one or more requests failed.' );
  });

通过一些小的重构,您可以在大约 2 分钟内实现这一点。

或者,如果您控制服务器,则可以创建一个服务器端点来执行一个请求中的所有检查。

于 2013-04-05T11:57:51.157 回答
1

你可以这样做:

var urls= ['url1', 'url2', 'url3', 'url4'];
function doTheUrl() {
    if (urls.length === 0) {
        alert('All urls are done now.');
        return;
    }

    var url = urls.pop();
    $.ajax({
        url: "/DoTheJob",
        complete: function () {
            doTheUrl();
        }
    });
};
于 2013-04-05T12:01:18.933 回答
0

也许你可以试试这个。我只是运行一个空的 while 循环,以便在返回所有 ajax 调用之前不会命中 return 语句。

function countHealthy(urls) {
  var healthy = 0;
  var urlCount = urls.length;
  var numberOfAjaxCallsReturned = 0;
  for (var i = 0; i < urls.length; ++i) {
    $.ajax({url: urls[i], async: true, id: i})
      .done(function (data) { 
              ++healthy;
              numberOfAjaxCallsReturned++;
      });
    }
    while(numberOfAjaxCallsReturned!=urlCount)
    {
    }
    return healthy;
}
于 2013-04-05T12:05:58.167 回答
0

如果您有一个复杂的页面,您将需要跟踪并等待特定的异步调用返回。这是因为其他非紧急呼叫可能正在运行。

话虽如此,对于简单的页面,您只需检查并等待没有电话。此 jQuery 脚本每季度检查一次,以查看每季度每秒是否有当前的异步请求。一旦没有,您将继续。

    var WaitForAjax = function()
    {
        if (jQuery.active == 0){
        }
        else
        {
            setTimeout(WaitForAjax, 250);
        }
    }

    function RunIt()
    {
        //IssueAjaxCalls would be where you make all your Ajax calls.
        IssueAjaxCalls();

        WaitForAjax();

        //The KeepGoing function won't get called until there are no more Ajax calls pending.
        KeepGoing();
    }
于 2016-04-05T16:10:42.580 回答
0

首先,您在每个 for 循环上发出 ajax 请求,这似乎有点浪费您的服务器资源。如果该函数会被大量调用,那么我建议您重构代码以尽可能少地进行查询。

无论如何,这就是我的做法

function countHealthy(urls) {

    var healthy = 0;
    var reqs = [];

    for (var i = 0; i < urls.length; ++i) {
        reqs.push(
            $.ajax({
                url: urls[i],
                id: i
            })
        );
    }
}


$.when.apply($, reqs).then(function() {
    // On success
    ++healthy;
}).fail(function() {
    // When failed
}).always(function() {
    // this will be run no matter the outcome
});

没有机会尝试一下,所以我不确定我是否犯了语法错误等。更改您的代码:

已删除async = true,如果您之前在代码中的某处将其设置为 false,请忽略它。

您可以了解“when.apply”的工作原理, 来源

于 2017-05-01T22:06:23.900 回答