Tìm kiếm trang web

javascript - Làm thế nào để tạo một vòng lặp bất đồng bộ sạch?


Theo các tiêu chuẩn REST điển hình, tôi đã tách các tài nguyên của mình thành các điểm cuối và các cuộc gọi riêng biệt. Hai đối tượng chính ở đây là List và Item (và tất nhiên, một danh sách có một danh sách các mục, cũng như một số dữ liệu khác liên quan đến nó).

Vì vậy, nếu một người dùng muốn truy xuất các danh sách của mình, anh ta có thể thực hiện một yêu cầu Get đến api/Lists

Sau đó người dùng có thể muốn lấy các mục trong một trong những danh sách đó và thực hiện một lệnh Get đến api/ListItems/4 trong đó số 4 được tìm thấy từ List.listId lấy được trong lần gọi trước.

Điều này thì tốt và hợp lý: thuộc tính options.complete của $.ajax cho phép tôi chỉ đến một phương thức callback, vì vậy tôi có thể hợp lý hóa hai sự kiện này.

Nhưng mọi thứ trở nên rất lộn xộn nếu tôi muốn lấy các phần tử cho tất cả các danh sách liên quan. Ví dụ, giả sử tôi có một hàm thư viện gọi là makeGetRequest nhận đầu cuối và hàm callback, để làm cho mã này gọn gàng hơn. Chỉ việc lấy 3 phần tử theo cách đơn giản sẽ dẫn đến kết quả như sau:

var success1 = function(elements){
    var success2 = function(elements){
       makeGetRequest("api/ListItems/3", finalSuccess);
    }
    makeGetRequest("api/ListItems/2", success2);
}
makeGetRequest("api/ListItems/1", success1);

Kinh tởm! Đây là kiểu thứ mà trong lập trình 101 chúng ta bị mắng thậm tệ và bị chỉ vào các vòng lặp. Nhưng làm thế nào bạn có thể làm điều này với một vòng lặp, mà không phải dựa vào bộ nhớ ngoài?

for(var i : values){
    makeGetRequest("api/ListItems/" + i, successFunction);
}

function successFunction(items){
    //I am called i-many times, each time only having ONE list's worth of items!
}

Và ngay cả với việc lưu trữ, tôi sẽ phải biết khi nào tất cả đã hoàn tất và lấy dữ liệu của họ, và gọi một hàm chính nào đó để lấy tất cả dữ liệu đã thu thập và làm gì đó với nó.

Có phương pháp nào để xử lý chuyện này không? Chuyện này chắc hẳn đã được giải quyết nhiều lần trước đây...

Câu trả lời #1

Hãy thử sử dụng một chồng các tham số endpoint:

var params = [];
var results [];

params.push({endpoint: "api/ListItems/1"});
params.push({endpoint: "api/ListItems/2"});
params.push({endpoint: "api/ListItems/3"});
params.push({endpoint: "api/ListItems/4"});

Sau đó bạn có thể làm cho nó đệ quy trong trình xử lý thành công của bạn:

function getResources(endPoint) {

   var options = {} // Ajax Options
   options.success = function (data) {
       if (params.length > 0) {
           results.push({endpoint: endpoint, data: data});
           getResources(params.shift().endpoint);
       }
       else {
          theMasterFunction(results)
       }
   }

   $.get(endPoint, options)
}

Và bạn có thể bắt đầu nó với một cuộc gọi đơn lẻ như thế này:

getResources(params.shift().endpoint);

Chỉnh sửa:

Để giữ mọi thứ tự chứa và không nằm trong phạm vi toàn cục, bạn có thể sử dụng một hàm và cung cấp một callback:

function downloadResources(callback) {

    var endpoints = [];
    var results [];

    endpoints.push({endpoint: "api/ListItems/1"});
    endpoints.push({endpoint: "api/ListItems/2"});
    endpoints.push({endpoint: "api/ListItems/3"});
    endpoints.push({endpoint: "api/ListItems/4"});

    function getResources(endPoint) {
        var options = {} // Ajax Options
        options.success = function (data) {
           if (endpoints.length > 0) {
               results.push({endpoint: endpoint, data: data});
               getResources(endpoints.shift().endpoint);
           }
           else {
              callback(results)
           }
        }
       $.get(endPoint, options)
    }

    getResources(endpoints.shift().endpoint);

}

Đang sử dụng:

downloadResources(function(data) {
   // Do stuff with your data set
});

Câu trả lời #2

Câu trả lời của dmck có lẽ là lựa chọn tốt nhất của bạn. Tuy nhiên, một lựa chọn khác là thực hiện tùy chọn danh sách hàng loạt, để API của bạn hỗ trợ các yêu cầu như api/ListItems/?id=1&id=2&id=3.

Bạn cũng có thể thực hiện một endpoint tìm kiếm API, nếu điều đó phù hợp hơn với thẩm mỹ cá nhân của bạn.