Trước hết, bạn phải quyết định nếu bạn muốn ba ajax của bạn gọi để được xử lý song song (chạy tất cả cùng một lúc, với thời gian chạy ít hơn tổng thể) hoặc theo thứ tự mà một cuộc gọi ajax chạy, hoàn thành và sau đó bạn khởi chạy cuộc gọi ajax tiếp theo. Đây là một quyết định thiết kế quan trọng tác động đến cách bạn làm điều này.
Khi bạn sử dụng $.when()
, bạn sẽ khởi chạy cả ba cuộc gọi ajax song song. Nếu bạn kiểm tra kết quả chỉ khi tất cả đã hoàn thành, bạn vẫn có thể xử lý kết quả theo một thứ tự cụ thể (vì bạn sẽ chỉ xử lý chúng khi tất cả kết quả có sẵn và chúng sẽ có sẵn theo thứ tự được yêu cầu). Nhưng, khi thực hiện nó theo cách này, tất cả các cuộc gọi ajax sẽ được gửi đi ngay lập tức. Điều này sẽ cung cấp cho bạn một thời gian end-to-end tốt hơn vì vậy nếu điều này là khả thi cho các loại yêu cầu, đây thường là một cách tốt hơn để làm điều đó.
Để làm điều đó, bạn có thể cơ cấu lại những gì bạn phải một cái gì đó như thế này:
chạy song song
var files = [
'url1', 'url2', 'url3'
];
$.when($.ajax(files[0]),$.ajax(files[1]),$.ajax(files[2])).done(function(a1, a2, a3) {
var results = [];
results.push(a1[0]);
results.push(a2[0]);
results.push(a3[0]);
console.log("got all results")
});
Bởi vì bạn đang chờ đợi cho đến khi xử lý .done()
cho $.when()
đã được gọi là, tất cả các kết quả ajax đã sẵn sàng cùng một lúc và chúng được trình bày bởi $.when()
theo thứ tự chúng được yêu cầu (bất kể cái nào thực sự đã hoàn thành trước), vì vậy bạn nhận được kết quả nhanh nhất có thể và chúng được trình bày theo thứ tự có thể dự đoán được. Lưu ý, tôi cũng đã chuyển định nghĩa của mảng results
thành bộ xử lý thực hiện $.when()
vì đó là nơi duy nhất bạn biết dữ liệu thực sự hợp lệ (vì lý do thời gian).
chạy song song - Lặp Arbitrary Chiều dài Mảng
Nếu bạn đã có một mảng lâu hơn, bạn có thể tìm thấy nó tốt hơn để lặp qua mảng của bạn với một cái gì đó giống như .map()
để xử lý tất cả trong một vòng lặp thay hơn cách liệt kê chúng riêng lẻ:
var files = [
'url1', 'url2', 'url3', 'url4', 'url5', 'url6', 'url7'
];
$.when.apply($, files.map(function(url) {
return $.ajax(url);
})).done(function() {
var results = [];
// there will be one argument passed to this callback for each ajax call
// each argument is of this form [data, statusText, jqXHR]
for (var i = 0; i < arguments.length; i++) {
results.push(arguments[i][0]);
}
// all data is now in the results array in order
});
chuỗi Ajax gọi
Nếu, mặt khác, bạn thực sự muốn sắp xếp các cuộc gọi ajax để cuộc gọi thứ hai không bắt đầu cho đến khi cuộc gọi đầu tiên kết thúc (có thể cần thiết nếu cuộc gọi ajax thứ hai cần kết quả từ cuộc gọi ajax đầu tiên để biết yêu cầu hoặc làm gì), thì bạn cần một mẫu thiết kế hoàn toàn khác và $.when()
không phải là cách để đi chút nào (nó chỉ thực hiện các yêu cầu song song). Trong trường hợp đó, bạn có thể chỉ muốn kết quả chuỗi của bạn với x.then().then()
và sau đó bạn có thể xuất báo cáo nhật ký theo thứ tự mà bạn yêu cầu như thế này.
$.ajax(files[0]).then(function(data0) {
console.log("step 1.0");
return $.ajax(files[1]);
}).then(function(data1) {
console.log("step 1.1");
return $.ajax(files[2]);
}).done(function(data2) {
console.log("step 1.2");
// all the ajax calls are done here
console.log("step 2");
});
điều khiển Output:
step 1.0
step 1.1
step 1.2
step 2
Cấu trúc này cũng có thể được đưa vào một vòng lặp để tự động chạy nó cho N cuộc gọi ajax tuần tự nếu mảng của bạn các tập tin dài. Trong khi bạn có thể thu thập kết quả khi bạn đi vào mảng results
, thường là lý do mọi thứ được thực hiện tuần tự là kết quả trước đó được tiêu thụ bởi cuộc gọi ajax tiếp theo, do đó bạn thường chỉ cần kết quả cuối cùng. Nếu bạn muốn thu thập kết quả khi bạn đi, bạn có thể đẩy chúng vào mảng results
ở mỗi bước.
Lưu ý, những lợi thế hứa hẹn cung cấp ở đây để bạn có thể thực hiện các thao tác chuỗi trong khi vẫn ở cùng mức độ lồng nhau và không được lồng ghép thêm nữa.
Chuỗi Ajax cuộc gọi - Lặp Arbitrary Chiều dài Mảng
Dưới đây là những gì các trình tự sẽ như thế nào trong một vòng lặp:
var files = [
'url1', 'url2', 'url3', 'url4', 'url5', 'url6', 'url7'
];
var results = [];
files.reduce(function(prev, cur, index) {
return prev.then(function(data) {
return $.ajax(cur).then(function(data) {
console.log("step 1." + index);
results.push(data);
});
})
}, $().promise()).done(function() {
// last ajax call done
// all results are in the results array
console.log("step 2.0");
});
điều khiển Output:
step 1.0
step 1.1
step 1.2
step 1.3
step 1.4
step 1.5
step 1.6
step 2
Phương thức Array.prototype.reduce()
wo rks handily ở đây vì nó tích lũy một giá trị duy nhất khi bạn xử lý từng phần tử mảng riêng lẻ, đó là những gì bạn cần làm khi bạn thêm .then()
cho mỗi phần tử mảng. Việc lặp lại .reduce()
được bắt đầu bằng lời hứa trống/đã giải quyết với $().promise()
(có nhiều cách khác để tạo lời hứa như vậy), điều này chỉ cung cấp cho chúng tôi thứ gì đó để bắt đầu thực hiện .then()
trên đó đã được giải quyết.
Sự cố bạn đang gặp phải với vấn đề này là gì? Các yêu cầu có thể hoàn thành theo thứ tự khác, vì vậy bạn có thể kết thúc bằng 'bước 1.2, bước 1.0, bước 1.1, bước 2', nhưng mảng sẽ luôn được điền trước khi 'then()' được thực hiện. –
Tôi hoàn toàn cần chúng để hoàn thành đúng thứ tự. Điều quan trọng là mã hoạt động chính xác. – Ciel
Tôi nhận được các kết quả khác nhau.Tôi nhận được 'bước 2' bắn trước bất kỳ bước 1s nào. – Ciel