Почему я вижу повторяющиеся асинхронные ответы javascript? - PullRequest
1 голос
/ 18 августа 2011

Я пытаюсь понять, почему я вижу следующее:

Я запускаю несколько асинхронных запросов внутри цикла for, а затем просто распечатываю ответы. Вот очень упрощенная версия того, что я делаю:

function getStuff(){
   var singers = ['marley','matthews','johnson','buffett'];
   for(lastname in singers){
       var lastName = singers[lastname];
       log("Making request for "+ singers[lastname]);
       makeAsyncRequest(singers[lastname], function(response){
               //this is the callback when the async request returns
               log("RESPONSE - "+lastName+": "+response);
       });
   }
}

Если я запускаю код синхронно (async: false), я каждый раз получаю следующие результаты, как и ожидалось:

Making request for marley
Making request for matthews
Making request for johnson
Making request for buffett
RESPONSE - marley: bob
RESPONSE - johnson: jack
RESPONSE - matthews: dave
RESPONSE - buffett: jimmy 

Когда я бегу асинхронно, я вижу результаты, подобные следующим. Я понимаю, что ответы могут вернуться не в порядке. Но я не понимаю, когда они выходят из строя, почему я вижу повторяющиеся значения? Например, я мог бы увидеть:

Making request for marley
Making request for matthews
Making request for johnson
Making request for buffett
RESPONSE - marley: bob
RESPONSE - johnson: dave
RESPONSE - matthews: dave
RESPONSE - buffett: jimmy 

Обратите внимание, что «Дейв», кажется, возвращается дважды? Я бы понял, если бы значения 'jack' и 'dave' были переключены, например так:

Making request for marley
Making request for matthews
Making request for johnson
Making request for buffett
RESPONSE - marley: bob
RESPONSE - johnson: dave
RESPONSE - matthews: jack
RESPONSE - buffett: jimmy 

Но я не понимаю, почему параметр "response" в обратном вызове, кажется, устанавливается в одно и то же значение дважды? Я пропускаю что-то простое здесь?

Спасибо за любую помощь!

Ответы [ 4 ]

1 голос
/ 22 августа 2011

Цикл не имеет собственной области видимости. Проблема в том, что существует только одна переменная lastName, и когда асинхронный запрос возвращает его содержимое, оно не всегда будет тем содержимым, которое вы ему присвоили в итерации.

Вы должны прочитать и понять как работает область в JavaScript .

Решением может быть дополнительное замыкание в вашем цикле:

function getStuff(){
   var singers = ['marley','matthews','johnson','buffett'];
   for( lastname in singers ) {
       function( lastName ) {
           log( "Making request for "+ lastName );
           makeAsyncRequest( lastName, function(response) {
                   //this is the callback when the async request returns
                   log("RESPONSE - "+lastName+": "+response);
           } );
       }( singers[lastname] );
   }
}
0 голосов
/ 18 августа 2011

попытайтесь сохранить копию фамилии в цикле for:

function getStuff()
{
   var singers = ['marley','matthews','johnson','buffett'];
   for(lastname in singers)
   {
       var currentName = lastname;
       log("Making request for "+ singers[currentName]);
       makeAsyncRequest(singers[lastname], function(response)
       {

           //this is the callback when the async request returns
           log("RESPONSE - "+singers[currentName ]+": "+response);
       });
   }
}
0 голосов
/ 22 августа 2011

В этом случае для службы удаленного отдыха требуется базовая аутентификация. Я посылал разные имена пользователей и пароли каждый раз через цикл. Я наконец понял, что основные учетные данные аутентификации кэшируются на стороне сервера.

На стороне сервера, если служба обнаружила допустимый файл cookie с именем JSESSIONID, она игнорировала имя пользователя и пароль Basic Auth в заголовке запроса http.

Итак, решение было использовать плагин cookie Jquery и обязательно удалять JSESSIONID для каждого запроса следующим образом:

$.cookie('JSESSIONID', null {path: '/pathToCookie'});
0 голосов
/ 18 августа 2011

У вас есть состояние гонки. Значение singer [name] в вашем обработчике ответов полностью зависит от состояния цикла for (). Как только вы выполняете асинхронные запросы, вполне возможно выйти из синхронизации, если какой-либо запрос задерживается (net.burp , медленный сервер и т.д ...).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...