Sử dụng closure
. Hãy để tôi chỉ cho bạn một ví dụ đơn giản
// JavaScript on Client-Side
window.onload = function() {
var f = (function() {
for (i = 0; i < 3; i++) {
(function(i){
var xhr = new XMLHttpRequest();
var url = "closure.php?data=" + i;
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText); // 0, 1, 2
}
};
xhr.send();
})(i);
}
})();
};
// Server-Side (PHP in this case)
<?php
echo $_GET["data"];
?>
Trong trường hợp của bạn ... quấn cuộc gọi không đồng bộ/chức năng với một đóng
for (var i=0; i< this.selectedAvailableUnits.length; i++) {
(function(i) { // <--- the catch
var unit = this.selectedAvailableUnits[i];
var unitId = unit.unitId;
var url = '/incident/' + currentIncidentId + '/assignUnit/' + unitId
$http.post(url).then(function(response) {
// DOING SOMETHING
}, function(error) {
alert(error);
});
})(i); // <---- (the i variable might be omitted if it's not needed)
}
Phần dưới đây không liên quan trực tiếp đến câu hỏi mà đúng hơn là các nhận xét liên quan đến câu trả lời này.
Ví dụ nộp jsFiddle đề cập trong các ý kiến và trình bày dưới đây là lỗi và như vậy nó không chứng minh bất cứ điều gì.
Đúng là đoạn mã này, thậm chí không sử dụng đóng cửa, mang lại 'Hello Kitty' ba lần; trên thực tế, nếu bạn thay thế phương thức console.log()
bằng một phương thức alert()
, bạn sẽ thấy rằng nó mang lại 'Hello Kitty' sáu, chín hoặc thậm chí mười hai lần. Vì vậy, cái quái gì đang diễn ra;) làm thế nào có thể để cửa sổ cảnh báo bật lên sáu, chín hay mười hai lần trong vòng lặp ba lần lặp?
// your example (a) // my comments
//
var f = (function() {
for (i = 0; i < 3; i++) {
//(function(){ // this way you can't have multiple scopes
var xhr = new XMLHttpRequest();
var url = "closure.php?data=your-data"; // use /echo/html/ for testing on jsfiddle.net
xhr.open("GET", url, true); // use POST for testing on jsfiddle.net
xhr.onreadystatechange = function() { // this way you might catch all readyStage property values
callback(); // this way the callback function will be called several times
};
xhr.send();
//})();
}
})();
var callback = function() {
console.log("Hello Kitty"); // or use alert("Hello Kitty");
};
Output:
GET http://fiddle.jshell.net/_display/closure.php?data=your-data 404 (NOT FOUND)
(9) Hello Kitty
Như bạn có thể thấy, chúng tôi đã có một lỗi và chín 'Hello Kitty' đầu ra liên tiếp :) Trước khi tôi thay đổi chức năng ở trên chúng ta hãy xem hai quan trọng điều
cửa hàng kiện
onreadystatechange
Đầu tiên một hàm hoặc tham chiếu được gọi tự động mỗi lần thay đổi thuộc tính readyState
trong khi thuộc tính status
giữ trạng thái của đối tượng XMLHttpRequest.
readyState
tài sản giá trị có thể
- 0: Yêu cầu không được khởi tạo
- 1: kết nối máy chủ thành lập
- 2: yêu cầu nhận được
- 3: thực hiện yêu cầu
- 4: yêu cầu hoàn thành và phản ứng đã sẵn sàng
status
tài sản giá trị có thể
- 200: OK
- 404: Không tìm thấy
Second
Như tôi đã nói trong các ý kiến, jsfiddle.net là không đáng tin cậy cho thử nghiệm các đoạn mã không đồng bộ mà không có một số thay đổi. Nói cách khác phương pháp GET
nên được thay đổi để POST
và url
tài sản phải được thay đổi để liên kết này /echo/html/
(để biết thêm tùy chọn hãy xem jsFiddle documentation)
Bây giờ, chúng ta hãy thay đổi ví dụ từ trên (và làm theo ý kiến trong mã)
// corrected example (b)
//
var f = (function() {
for (i = 0; i < 3; i++) {
//(function(i){ // uncomment this line for the 3rd output
var xhr = new XMLHttpRequest();
var url = "/echo/html";
var data = "data";
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
//if (xhr.readyState == 4 && xhr.status == 200) { // uncomment this line for the 4th output
callback(i, xhr.readyState); // uncomment this line for the 4th output
//}
};
xhr.send(data);
//})(i); // uncomment this line for the 3rd output
}
})();
var callback = function(i, s) {
console.log("i=" + i + " - readyState=" + s + " - Hello Kitty");
};
sản lượng 1: // sáu đầu ra
(4) i=3 - readyState=1 - Hello Kitty // four outputs related to readyState value 'server connection established'
i=3 - readyState=2 - Hello Kitty // related to readyState value 'request received'
i=3 - readyState=4 - Hello Kitty // related to readyState value 'request finished and response is ready'
đầu ra 2: // sáu đầu ra
(2) i=3 - readyState=1 - Hello Kitty // two outputs related to readyState value 'server connection established'
i=3 - readyState=2 - Hello Kitty // related to readyState value 'request received'
(3) i=3 - readyState=4 - Hello Kitty // three outputs related to readyState value 'request finished and response is ready'
Không có bất kỳ thay đổi nào được thực hiện trong ví dụ (b), chúng tôi có hai kết quả đầu ra khác nhau. Như bạn có thể thấy, các kết quả đầu ra khác nhau cho các giá trị thuộc tính readyState khác nhau đã được tạo ra. Nhưng giá trị của i
vẫn giữ nguyên.
3 đầu ra: // sau uncommenting các dòng cho đầu ra 3 showned trên trong ví dụ (b)
i=0 - readyState=2 - Hello Kitty // related to readyState value 'request received'
i=0 - readyState=4 - Hello Kitty // related to readyState value 'request finished and response is ready'
i=1 - readyState=2 - Hello Kitty // ...
i=1 - readyState=4 - Hello Kitty // ...
i=2 - readyState=2 - Hello Kitty
i=2 - readyState=4 - Hello Kitty
Vì vậy, sau khi uncommenting các chức năng mà giữ i
như một cuộc tranh cãi, chúng ta thấy rằng giá trị trong số i
đã được lưu. Nhưng điều này vẫn không chính xác vì có sáu đầu ra và chúng ta chỉ cần ba. Như chúng ta đã không cần tất cả các giá trị của readyState
hoặc status
tài sản của đối tượng XMLHttpRequest
, chúng ta hãy bỏ ghi chú hai dòng cần thiết cho đầu ra thứ tư
đầu ra 4: // sau uncommenting các dòng cho đầu ra 4rd showned trên trong ví dụ (b) - cuối cùng là ba kết quả đầu ra
i=0 - readyState=4 - Hello Kitty
i=1 - readyState=4 - Hello Kitty
i=2 - readyState=4 - Hello Kitty
Cuối cùng, đây là phiên bản đúng của đoạn mã và đây là những gì chúng tôi cần.
Một cơ chế toàn năng, toàn năng khác (như tôi đã nói trước đây) sẽ là hàm bind()
mà tôi không thích vì nó chậm hơn so với đóng.
bạn có thể kiểm tra trong tab mạng trình duyệt, chỉ thực sự một yêu cầu được gửi không ?? – harishr
@ mr-câu hỏi xin vui lòng dành thời gian của bạn để xem xét các câu trả lời và chọn đúng – domokun