2013-05-14 3 views
-1

В расширении chrome Я пишу, мне нужно проверить некоторые объекты, которые я сохранил в localStorage, на мой сервер. Для этого я создал цикл for, который просто отправляет данные для каждого элемента localstorage и должен что-то делать с ответом. Код что-то вроде этого:Ajax Inside For Loop

for (var key in localStorage) { 
     if (! some condition) 
         continue; 

     var httpRequest = new XMLHttpRequest(); 
     httpRequest.onreadystatechange = function() { 
      if (httpRequest.readyState === 4 && httpRequest.response == 200) { 
       do something with 'key' from the for loop 
      } 
     } 
     }; 
     var url = BASE_PATH ; 
     httpRequest.open("POST", url); 
     httpRequest.send(some data); 
        } 

Однако во время отладки это, кажется, что в ответ АЯКС, «ключ» из цикла для не ключ мне нужно: я ожидал, чтобы получить тот же ключ цикл for, который соответствует каждому вызову ajax, то, что я получил, был тем же ключом для всех вызовов ajax. Я делаю что-то неправильно или ожидаю чего-то, что невозможно? Я думал, что, поскольку ajax находится внутри функции закрытия, значения хранятся в памяти или что-то в этом роде.

+0

Возможный дубликат [Javascript закрытия внутри петель - простой практический пример] (http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) –

+0

Существует ")" что не должно быть там, если (httpRequest.readyState === 4) && httpRequest.response == 200) –

ответ

1

Извлечение фактического Ajax вызова в отдельную функцию:

function AjaxCall(key) { 
    var httpRequest = new XMLHttpRequest(); 
    httpRequest.onreadystatechange = function() { 
    if ((httpRequest.readyState === 4) && (httpRequest.response == 200)) { 
     do something with 'key' from the for loop 
    } 
    }; 
    var url = BASE_PATH ; 
    httpRequest.open("POST", url); 
    httpRequest.send(some data); 
} 

for (var key in localStorage) { 
    if (some condition) {  
    AjaxCall(key); 
    }  
} 

Причина в том, что вы создаете закрытие с помощью функции передается onreadystatechange. Все эти функции указывают на ту же переменную key, которая содержит только одно (последнее) значение для всех вызовов Ajax после завершения цикла.

Когда вы создаете отдельную функцию (например, AjaxCall() в моем примере), вы создаете другой контекст для каждого вызова и, следовательно, все обратные вызовы указывают на разные клавиши.

+0

Как я уже сказал в вопросе, есть a), которого не должно быть. Кроме того, «else» не требуется, потому что, если продолжить, код ниже не будет выполнен. Однако, хорошее объяснение. –

+0

Кроме того, в цикле for, если вы еще не используете метод hasOwnProperty, вы можете попробовать его. Это предотвратит отправку имени свойства или имени функции, которое наследуется от типа объекта. – jhorton

+0

@jhorton: Ни одно из собственных свойств, определенных в 'Object.prototype', не перечислимо. Это будет прекрасно, пока на прототипе не будут определены никакие настраиваемые, перечислимые свойства. –