2013-04-05 230 views
6

我想写一个函数执行一打异步ajax请求,等待所有的完成,然后返回聚合信息。像:等待异步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:++健康线程是否安全?

回答

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分钟内实现这一点。

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

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(); 
     } 
    }); 
}; 
+0

其实我不认为这会工作。在函数结尾处有一个隐式的'return'。所以当$ .ajax调用被放在堆栈上时,所有事情都会继续前进,并且函数将退出。我现在会倒下。 – the0ther 2015-03-16 16:19:34

0

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

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; 
} 
+1

这个表现很糟糕,在我看来没有用。 – 2015-02-25 13:47:51

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(); 
    } 
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”作品的想法, source