2013-04-05 33 views
6

Tôi muốn viết một hàm thực hiện một tá yêu cầu ajax không đồng bộ, đợi cho đến khi hoàn tất và sau đó trả về thông tin tổng hợp. Giống như:Đợi yêu cầu async ajax để hoàn thành

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: Chủ đề lành mạnh ++ có an toàn không?

Trả lời

6

Javascript không có chủ đề để an toàn chủ đề không phải là vấn đề. Tuyên bố trả về của bạn là vấn đề, nó cần phải đi trong gọi lại rằng các cuộc gọi ajax thực thi khi hoàn thành. Kể từ khi ajax xảy ra không đồng bộ, như mã của bạn là viết tắt, câu lệnh return sẽ kích hoạt trước khi tất cả các yêu cầu trả về.

Bạn có thể muốn xem query deferreds, dường như được sinh ra cho loại điều này. Trực tiếp từ liên kết đó

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.'); 
    }); 

Với một số phép tái cấu trúc nhỏ bạn có thể triển khai trong khoảng 2 phút.

Hoặc, nếu bạn kiểm soát máy chủ, bạn có thể tạo điểm cuối máy chủ thực hiện tất cả việc kiểm tra trong một yêu cầu.

1

Bạn có thể làm điều này:

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

thực sự tôi không nghĩ rằng đây sẽ làm việc. có một 'return' tiềm ẩn ở cuối hàm. do đó, khi cuộc gọi $ .ajax được đặt trên ngăn xếp, mọi thứ tiếp tục di chuyển cùng và chức năng thoát. tôi sẽ downvote bây giờ. – the0ther

0

lẽ bạn có thể thử loại này. Tôi chỉ đơn giản là chạy một vòng lặp trống rỗng để báo cáo trả về không được nhấn cho đến khi tất cả các cuộc gọi ajax được trả về.

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

hiệu suất rất kém trên trang này, không hữu ích theo ý kiến ​​của tôi. –

0

Nếu bạn có một trang phức tạp, bạn sẽ muốn theo dõi và đợi cụ thể cho các cuộc gọi không đồng bộ của bạn để trả lại. Điều này là do các cuộc gọi khác, không có ý nghĩa, có thể đang chạy.

Điều đó đang được nói, đối với các trang đơn giản, bạn chỉ có thể kiểm tra và đợi ở đó để không có cuộc gọi nào. Kịch bản lệnh jQuery này kiểm tra mỗi quý để xem liệu có các yêu cầu không đồng bộ hiện tại mỗi quý thứ hai hay không. Khi không có, bạn sẽ tiếp tục.

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

Trước hết, bạn đang thực hiện yêu cầu ajax trên mỗi vòng lặp, điều này dường như lãng phí một chút tài nguyên máy chủ của bạn. Nếu chức năng đó sẽ được gọi rất nhiều thì tôi sẽ đề nghị bạn cấu trúc lại mã của bạn để thực hiện các truy vấn ít nhất có thể.

Anyways, đây là cách tôi muốn làm điều đó

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 
}); 

đã không có cơ hội để thử nó ra, vì vậy tôi không chắc chắn nếu tôi đã thực hiện một lỗi cú pháp, vv Thay Đổi Của Bản đoạn mã của bạn:

Đã xóa async = true, bỏ qua điều này nếu bạn đã đặt mã này sai ở đâu đó trong mã của bạn trước đây.

Bạn có thể nhận được một ý tưởng về cách "when.apply" hoạt động, source

Các vấn đề liên quan