2011-08-08 27 views
13

Tôi tự hỏi làm thế nào để thực hiện cuộc gọi ajax theo nhóm n.Làm cách nào để tạo các yêu cầu ajax trong jQuery?

Đây là trường hợp sử dụng của tôi:

Tôi có bảng hiển thị dữ liệu sử dụng. Bạn có thể đi sâu vào từng hàng và nếu mỗi hàng có một thuộc tính chung mà bạn có thể đi sâu vào, bạn có thể chọn xem chi tiết tất cả các hàng cùng một lúc. Đối với mỗi hàng, một cuộc gọi ajax được thực hiện để tìm nạp dữ liệu được thêm vào bảng.

Trong một số trường hợp nhất định, có thể có tối đa 50 hàng để đi sâu vào cùng một lúc. Như bạn có thể tưởng tượng, điều đó đặt rất nhiều căng thẳng trên máy chủ. Làm thế nào tốt nhất tôi có thể gửi các cuộc gọi trong các lô nhỏ hơn mà chờ đợi trên lô trước khi chúng cháy?

Tôi biết có các plugin như hàng đợi tin nhắn jquery có khả năng giúp tôi, nhưng đây là dự án làm việc nên chúng tôi muốn tránh các plugin càng nhiều càng tốt.

+1

do đó hãy chắc quản lý hàng đợi riêng bạn :) –

+0

Câu trả lời này thường giúp http://stackoverflow.com/questions/42425885/trying-to-make-2-ajax -calls-via-jquery-and-sau-prepending-the-data-taken-from/42426722 # 42426722 –

Trả lời

16

Bạn có thể có một cái nhìn tại sử dụng jQuery.when, cho phép bạn thực hiện các chức năng gọi lại khi tất cả các yêu cầu đã hoàn tất.

$.when($.ajax("request1"), $.ajax("request2"), $.ajax("request3")) 
.done(function(data1, data2, data3){ 
     // Do something with the data 
}); 

Hoặc

$.when($.ajax("request1"), $.ajax("request2"), $.ajax("request3")) 
.then(successCallback, errorHandler); 

Xem post sau để biết thêm thông tin.

Ngoài ra, tôi không chắc chắn rằng sự e ngại của bạn khi sử dụng plugin sẽ bị ảnh hưởng bởi thực tế bạn đang ở trong môi trường làm việc, đặc biệt nếu nó đơn giản hóa công việc của bạn. Do đó cho phép làm việc hiệu quả hơn. Cấp cho bạn phải chọn các plugin của bạn một cách cẩn thận, vì chất lượng và bảo trì lâu dài có thể là một vấn đề.

+1

jQuery [Đối tượng trì hoãn] (http://api.jquery.com/category/deferred-object/) chắc chắn là cách để đi khi xử lý các yêu cầu không đồng bộ. Việc sử dụng $ .when và $ .done khi xử lý các đối tượng lời hứa $ .ajax và mã được tạo bởi một setTimeout đã làm cho mã của tôi sạch hơn và dễ đọc hơn. Cuộc gọi tốt. – stinkycheeseman

+0

Có hiểu $ .when() nhưng có vẻ cồng kềnh để sử dụng cho trường hợp của tôi là truy vấn 5K xhr2, gửi hàng loạt 50. (Chrom ném lỗi bộ nhớ với máy chủ SPDY), Chromium cuối cùng sẽ sửa, nhưng tôi cần điều chỉnh hiện nay. Tôi nghĩ rằng tôi có thể thử gợi ý đệ quy dưới đây. Điều đó có đúng không? –

7

Cuộc gọi Ajax bằng jQuery thường không đồng bộ. Vì vậy, nếu bạn có 50 hàng, jQuery sẽ gửi không đồng bộ tất cả 50 yêu cầu - bạn không thể kiểm soát chuỗi xử lý khi bạn nhận được phản hồi từ máy chủ.

Bạn có thể sử dụng async: false trên $.ajax gọi như vậy mà chỉ có một yêu cầu được gửi đến máy chủ như bạn lặp qua hàng của bạn:

$.ajax({ 
    url: location, 
    data: params, 
    async: false, 
    success: function(msg) { // do something} 
}); 

Vấn đề với cách tiếp cận này (async: false) là người dùng có thể trải nghiệm một "đóng băng" hoặc trang không phản hồi.

Một cách khác là sử dụng đệ quy trong JavaScript để các cuộc gọi vẫn không đồng bộ nhưng các cuộc gọi ajax vẫn chờ đợi sự kiện thành công của mỗi hàng như sau:

var maxRows = 50; 

function myFunc(index) { 
    $.ajax({ 
     url: location, 
     data: params, 
     async: true, 
     success: function(msg) { 
      if (index < maxRows) { 
       // do something 
      } 
      else { 
       return; //index equals maxRows--stop the recursion 
      } 
      index++; 
      myFunc(index); //call the function again 
     } 
    }); 

    $(document).ready(function() { 
     myFunc(0);  
    }); 
} 
+0

Tôi cần thực hiện các truy vấn 5K xhr2, gửi các lô 50. (Chrome ném lỗi bộ nhớ với các máy chủ SPDY), Mọi người Chromium cuối cùng cũng sẽ sửa nhưng tôi cần điều chỉnh ngay bây giờ. Tôi nghĩ rằng cách tiếp cận đệ quy của bạn đã hứa hẹn. –

3

Tôi đồng ý với eicto: làm người quản lý tin nhắn của riêng bạn nếu bạn không thể tích hợp một trình quản lý khác. Đây là vết nứt của tôi lúc nhỏ:

var AjaxQueue = function(max) { 
    this.max = max; 
    this.requests = []; 
    this.current = 0; 
} 

AjaxQueue.prototype.ajax = function(opts) { 
    var queue = this; 
    opts.complete = function(jqXHR, textStatus) { 
    queue.current -= 1; 
    queue.send(); 
    }; 
    this.requests.push(opts); 
    this.send(); 
} 

AjaxQueue.prototype.send = function(opts) { 
    while (this.current < this.max && this.requests.length > 0) { 
    $.ajax(this.requests.unshift()); 
    this.current += 1; 
    } 
} 

Tôi chưa thử sử dụng, vì vậy chắc chắn có lỗi. Ngoài ra, giả sử bạn không sử dụng tùy chọn complete. Nó chỉ ghi đè nó. Nếu bạn là bạn có thể kiểm tra nó và chắc chắn rằng các chức năng hoàn chỉnh trước đó vẫn được gọi.

+0

Ah tuyệt vời này là hoàn hảo. Tôi sẽ chơi đùa với nó và xem tôi có thể làm gì. Mối quan tâm duy nhất của tôi là, có tiềm năng cho một điều kiện chủng tộc trong this.current không? Tôi biết hiếm khi 2 cuộc gọi ajax hoàn thành cùng một lúc, vì vậy có đáng để suy nghĩ không? – stinkycheeseman

+2

Không. Trình duyệt đảm bảo rằng hai hàm do người dùng định nghĩa không thể chạy cùng một lúc. Đây là lý do tại sao chạy một vòng lặp vô hạn trong khi sẽ khóa tương tác với trang web. Nó cũng làm cho mọi việc đơn giản hơn. –

+0

Bất kỳ cơ hội nào về ví dụ sử dụng? – PlanetWilson

0

Việc thực hiện các cuộc gọi lặp lại đệ quy cho tôi. Nhưng kể từ khi tôi nhận được 4K của các đốm màu XHR2 và tiết kiệm mỗi một trong IndexedDB (PouchDB). Tôi có chủ đề cho cả XHR2 và IDB đặt.Vì vậy, tôi phải phức tạp hơn một chút:

 for (var i in info.LayerInfo) { 
     var imageType = (info.LayerInfo[i].Class == "BASE") ? "jpg" : "png"; 
     info.LayerInfo[i].SaveCount = 0; 
     getLayer(0, info, info.LayerInfo[i], info.LayerInfo[i].Path, imageType); 
    } 
} 

function getLayer(index, info, layer, base, imageType) { 
    if (layer.Files.length == 0) { 
     console.log("Thread done: " + index + " SaveCount: " + layer.SaveCount); 
     return; 
    } 
    var val = layer.Files.shift(); 
    var path = base + "/" + val.id + "." + imageType; 
    $xhr.ajax({ 
     url: path, 
     dataType: "blob", 
     success: function (data) { 
      console.log("fetched: ", layer.Type + "-" + val.id); 
      saveBlob(data, val.size, val.id, layer.Type, index, info, layer, base, imageType); 
      if (index < maxThreads - 1) { 
       getLayer(++index, info, layer, base, imageType); 
      } else { 
       return; 
      } 
     } 
    }); 
} 

function saveBlob(blob, length, id, layerID, index, info, layer, base, imageType) { 
    if (blob.size != length) { 
     console.error("Blob Length found: ", blob.size, " expected: ", length); 
    } 
    var blobID = layerID + "-" + id; 
    var type = blob.type; 
    DB.putAttachment(blobID + "/pic", blob, type, function (err, response) { 
     if (err) { 
      console.error("Could store blob: error: " + err.error + " reason: " + err.reason + " status: " + err.status); 
     } else { 
      console.log("saved: ", response.id + " rev: " + response.rev); 
      layer.SaveCount++; 
      getLayer(index, info, layer, base, imageType); 
     } 
    }); 
} 
Các vấn đề liên quan