2012-01-04 19 views
8

Hãy để tôi giải thích mã của tôi một chút (Xin lỗi nếu có điều gì đó sai, tôi vừa viết ví dụ này từ đầu, nó rất gần với những gì tôi hiện có).Nhiều cuộc gọi ajax bên trong một hàm each() .. sau đó làm điều gì đó một khi TẤT CẢ chúng được hoàn tất?

HTML:

<form id="form"> 
    <!-- Friend 1 --> 
    Name 1: <input type="text" name="friendName1" id="friendName1" class="friendName" value=""><br /> 
    Email 1: <input type="text" name="friendEmail1" id="friendEmail1" value=""><br /><br /> 
    <!-- Friend 2 --> 
    Name 2:<input type="text" name="friendName2" id="friendName2" class="friendName" value=""><br /> 
    Email 2:<input type="text" name="friendEmail2" id="friendEmail2" value=""><br /><br /> 
    <!-- Friend 3 --> 
    Name 3:<input type="text" name="friendName3" id="friendName3" class="friendName" value=""><br /> 
    Email 3:<input type="text" name="friendEmail3" id="friendEmail3" value=""><br /><br /> 
    <!-- Friend 4 --> 
    Name 4:<input type="text" name="friendName4" id="friendName4" class="friendName" value=""><br /> 
    Email 4:<input type="text" name="friendEmail4" id="friendEmail4" value=""><br /><br /> 
    <!-- Submit --> 
    <input name="submit" type="submit" value="Submit"> 
</form> 

JS:

$("#form").submit(function(){ 

    $(".friendName[value!='']").each(function(){ 
     var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName',''); 
     if($("#"+idEmail+"[value!='']").length > 0){ 
      var name = $(this).val(); 
      var email = $("#"+idEmail).val(); 

      // Submit the ajax request 
      $.ajax({ 
       type: 'POST', 
       url: 'ajax/url', 
       data: { 
        name: name, 
        email: email 
       }, 
       success: function(json) { 
        // Log a console entry if our ajax request was successful 
        console.log(name + " was submitted via ajax"); 
       } 
      }); 
     } 
    }); 

    // Redirect the user to the thank you page 
    setTimeout(function() { window.location= '/thanks'; }, 2000); 

}); 

JSFiddle (redirect loại bỏ và ajax gọi thay thế bằng giao diện điều khiển log cho fiddle)

http://jsfiddle.net/cM5PX/

HTML là một biểu mẫu đơn giản, với tên người bạn và các trường nhập email của bạn bè.

JS có một chức năng, nếu tên và email được liên kết có giá trị, nó sẽ thực hiện cuộc gọi ajax.

Tôi cần một cách để các cuộc gọi ajax này chạy (có thể có 1 vòng lặp, có thể là 15) và sau khi hoàn tất, hãy chuyển hướng đến một trang mới.

Cách hiện tại tôi đang thực hiện điều đó thật khủng khiếp, vì tất cả cuộc gọi ajax đều không kết thúc trước khi trang chuyển hướng.

Tôi có thể làm gì để cải thiện điều này? Nó cần phải được đánh lừa bằng chứng và chỉ chuyển hướng một khi tất cả các cuộc gọi ajax đã hoàn thành (thành công hay lỗi, nó không quan trọng - nó chỉ cần chuyển hướng khi nó đã hoàn thành).

Tôi đã thử sử dụng async: false nhưng có vẻ như không tạo sự khác biệt.

Tôi đã nghĩ đến việc đặt bộ đếm trong mỗi chức năng và bộ đếm trong hàm thành công ajax và nếu cả hai khớp nhau, thì thực hiện chuyển hướng, nhưng tôi đang tìm một số hướng dẫn có kinh nghiệm hơn.

Trả lời

0

Theo mặc định $ .ajax là không đồng bộ. Trong băm tùy chọn được chuyển, hãy thêm

async: false 

Điều đó sẽ sắp xếp các cuộc gọi mà bạn đang thực hiện theo cách bạn muốn.


Sau khi nhận được comment từ poster ban đầu, giải pháp khả thi có thể làm như sau:

  • Bên trong trình gọi xác định số lượng cuộc gọi mà nên được thực hiện.
  • Lưu trữ kết quả này như là một biến địa phương trong phạm vi chức năng xử lý
  • Tạo một callback vào 'hoàn chỉnh:' rằng sẽ xem xét giá trị của các cuộc gọi
    • Nếu số lượng cuộc gọi được thực hiện là lớn hơn 0, sau đó giảm giá trị và trả lại
    • Nếu số lượng cuộc gọi đạt đến 0, hãy cập nhật window.location (thực sự nên sử dụng window.location.href làm cửa sổ.vị trí là một đối tượng nhưng các trình duyệt sẽ cho phép này và thực hiện một cách chính xác)

Lưu ý, tôi không có bất kỳ thông tin về chủ đề an toàn thực hiện loại hình hoạt động do đó, YMMV.


Ví dụ Code:

$("#form").submit(function(eventObject){ 
    var $ajaxFields= $(".friendName[value!='']").filter(function(index){ 
     var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName',''); 
     return ($("#"+idEmail+"[value!='']").length > 0); 
    }); 

    var numberToSubmit= $ajaxFields.length; 
    $ajaxFields.each(function(){ 
     var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName',''); 
     var name = $(this).val(); 
     var email = $("#"+idEmail).val(); 

     // Submit the ajax request 
     $.ajax({ 
      type: 'POST', 
      url: 'ajax/url', 
      data: { 
       name: name, 
       email: email 
      }, 
      success: function(json) { 
       // Log a console entry if our ajax request was successful 
       console.log(name + " was submitted via ajax"); 
      }, 
      error: function(jqXHR, textStatus, errorThrown) { 
       console.log("call not completed: "+textStatus); 
      }, 
      complete: function(jqXHR, textStatus) { 
       if(--numberToSubmit == 0) { 
        window.location.href= '/thanks'; 
       } 
      } 
     }); 
    }); 

    // Prevent default form submission 
    return false; 
}); 
+1

Và nó sẽ khóa giao diện người dùng. –

+0

Chỉ cần cập nhật câu hỏi của tôi, tôi đã thử sử dụng async: false nhưng dường như nó không tạo ra sự khác biệt và tôi thực sự không muốn trình duyệt đóng băng trong khi các cuộc gọi đang được thực hiện. – Latox

+0

Ah ok ... hãy để tôi đào một chút. –

2

Chỉ cần giữ một bộ đếm của các cuộc gọi AJAX và kiểm tra xem khi họ đều đã hoàn thành. Something như thế này:

$("#form").submit(function(){ 
    var ajaxMax = $(".friendName[value!='']").length, ajaxCounter = 0; 
    $(".friendName[value!='']").each(function(){ 
     var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName',''); 
     if($("#"+idEmail+"[value!='']").length > 0){ 
      var name = $(this).val(); 
      var email = $("#"+idEmail).val(); 

      // Submit the ajax request 
      $.ajax({ 
       type: 'POST', 
       url: 'ajax/url', 
       data: { 
        name: name, 
        email: email 
       }, 
       success: function(json) { 
        // Log a console entry if our ajax request was successful 
        console.log(name + " was submitted via ajax"); 
        if(++ajaxCounter >= ajaxMax) 
         window.location= '/thanks'; 
       } 
      }); 
     } 
    }); 
}); 
+0

Tôi chỉ nhận ra rằng mã tôi đăng sẽ không hoạt động chính xác, bởi vì bạn có câu lệnh "if", vì vậy bạn sẽ cần kiểm tra điều đó khi tính toán "max". –

27

Sử dụng deferred objects:

$("#form").submit(function(e){ 

    e.preventDefault(); 

    var calls = []; 

    $(".friendName[value!='']").each(function(){ 
     // Submit the ajax request 
     calls.push($.ajax({ 
      type: 'POST', 
      url: 'ajax/url', 
      data: { 
       name: name, 
       email: email 
      }, 
      success: function(json) { 
       // Log a console entry if our ajax request was successful 
       console.log(name + " was submitted via ajax"); 
      } 
     })); 
    }); 

    $.when.apply($, calls).then(function() { 
     window.location= '/thanks'; 
    }); 
}); 
+0

Điều này nghe có vẻ thông minh, tôi sẽ cung cấp cho nó một đi và cho bạn biết làm thế nào tôi đi. – Latox

+0

Điều này thật tuyệt vời, không có thắc mắc tại sao bạn có 157k! ;) Câu trả lời chính xác! –

6

Ok, điều này là khá dễ dàng kể từ khi bạn đang sử dụng jQuery. jQuery đi kèm với một nhà sản xuất lời hứa tích hợp cũng được kết nối với các cuộc gọi Ajax của jQuery. Điều đó nghĩa là gì? Vâng, chúng ta có thể dễ dàng thực hiện như sau:

var requests = [ ]; 

// ... 

// Submit the ajax request 
requests.push($.ajax({ 
    type: 'POST', 
    url: 'ajax/url', 
    data: { 
     name: name, 
     email: email 
    }, 
    success: function(json) { 
     // Log a console entry if our ajax request was successful 
     console.log(name + " was submitted via ajax"); 
    } 
})); 

// at this point we filled our array with jXHR objects which also inherit the promise API 

$.when.apply(null, requests).done(function() { 
    document.location.href = '/thanks'; 
}); 

Lưu ý: Mã trên sẽ chỉ kích hoạt nếu tất cả yêu cầu hoàn tất thành công. Nếu bạn cần xử lý trường hợp nếu một yêu cầu nhiều hơn không thành công, hãy sử dụng .then() hoặc .fail() thay vì .done().

+0

Felix đánh bại bạn! :(+1 mặc dù. – Latox

+1

thực sự, tôi đã làm quá nhiều 'blabla': p – jAndy

+1

SO là một nơi khó khăn;) –

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