Użyj closure
. Pokażę wam prosty przykład
// 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"];
?>
W twoim przypadku ... owinąć asynchroniczne wywołanie funkcji/z zamknięciem
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)
}
Poniższa sekcja nie jest bezpośrednio związany z pytaniem ale raczej do komentarzy związanych z tą odpowiedzią.
Przykład składać na jsFiddle wspomniano w komentarzach a poniżej jest błędny i jako taki nie dowodzi niczego.
To prawda, że ten fragment, nawet nie używając zamknięcia, trzy razy powoduje "Hello Kitty"; w rzeczywistości, jeśli zastąpisz metodę console.log()
za pomocą metody alert()
, zobaczysz, że daje ona "Hello Kitty" sześć, dziewięć lub nawet dwanaście razy. Więc, do cholery, jedziemy;) jak to możliwe, by okno alarmowe pojawiało się sześć, dziewięć lub dwanaście razy w pętli trzech iteracji ?!
// 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");
};
wyjściowa:
GET http://fiddle.jshell.net/_display/closure.php?data=your-data 404 (NOT FOUND)
(9) Hello Kitty
Jak można zobaczyć, mamy błąd i dziewięć wyjść „hello kitty” w wierszu :) Zanim zmienić funkcję powyżej Zobaczmy dwa ważne rzecz
Pierwsze
onreadystatechange
sklepy zdarzeń funkcja lub odniesienie do automatycznego wywoływania za każdym razem, gdy właściwość readyState
zmienia się, podczas gdy właściwość status
przechowuje stan obiektu XMLHttpRequest.
readyState
własności możliwe wartości
- 0: nie żądanie inicjowane
- 1: Połączenie serwera ustalone
- 2: żądanie odebrane
- 3: przetwarzanie żądania
- 4: żądania zakończone i odpowiedź jest gotowy
status
własności możliwe wartości
- 200: OK
- 404: Nie znaleziono strony
Second
Jak powiedziałem w komentarzach, jsfiddle.net nie jest wiarygodne testowanie fragmentów asynchronicznych bez pewnych zmian. Innymi słowy metoda GET
należy zmienić POST
a właściwość url
musi być zmieniony na ten link /echo/html/
(więcej opcji przyjrzeć jsFiddle documentation)
Teraz zmieńmy przykład z powyższego (i śledzić komentarze w kodzie)
// 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");
};
1. wyjście: // sześć wyjść
(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'
2-ty wyjście: // sześć wyjść
(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'
Bez żadnych zmian w przykładzie (b), mamy dwa różne wyjścia. Jak widać, różne wyniki dla różnych wartości właściwości readyState zostały wygenerowane. Ale wartość i
pozostała taka sama.
3-ty Wyjście: // po odkomentowanie linii za 3 wyjścia showned powyżej w przykładzie (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
Tak, po odkomentowanie funkcję, która utrzymuje i
jako argumentu, widzimy, że wartość z i
został zapisany. Ale to wciąż jest nieprawidłowe, ponieważ istnieje sześć wyników, a potrzebujemy tylko trzech. Ponieważ nie musimy wszystkie wartości readyState
lub status
właściwość obiektu XMLHttpRequest
, niech odkomentowaniu dwie linie potrzebne do czwartego wyjścia
4-ty Wyjście: // po odkomentowanie linie na wyjściu 4rd showned powyżej w Przykład (b) - w końcu trzy wyjścia
i=0 - readyState=4 - Hello Kitty
i=1 - readyState=4 - Hello Kitty
i=2 - readyState=4 - Hello Kitty
Wreszcie, powinno to być poprawna wersja fragmencie i to jest to, czego potrzebujemy.
Innym wszechmocnym, wszechpotężnym mechanizmem (jak symbolicznie powiedziałem wcześniej) byłaby funkcja bind()
, której nie lubię, ponieważ jest wolniejsza niż zamknięcie.
Czy można sprawdzić w zakładce przeglądarki internetowej, czy rzeczywiście tylko jedno żądanie zostało wysłane? – harishr
@ mr-question proszę nie spiesz się, aby przejrzeć odpowiedzi i wybrać poprawny – domokun