为什么我会看到重复的javascript异步响应?

时间:2011-08-18 16:05:11

标签: javascript jquery asynchronous

我试图理解为什么我会看到以下内容:

我在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 

注意'dave'似乎被退回两次?我会理解是否切换了'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 

但是我不明白为什么回调中的“响应”参数似乎被设置为两次相同的值?我忽略了一些基本的东西吗?

感谢您的帮助!

4 个答案:

答案 0 :(得分:1)

循环没有自己的范围。问题是,只有一个lastName变量,当异步请求返回时,其内容并不总是您在迭代中分配给它的内容。

您应该阅读并理解how the scope in JavaScript works

解决方案可能是循环中的另一个闭包:

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] );
   }
}

答案 1 :(得分:0)

尝试在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);
       });
   }
}

答案 2 :(得分:-1)

你有一个竞争条件。响应处理程序中的歌手[name]值完全取决于for()循环所处的状态。一旦执行异步请求,如果任何请求被延迟,则完全有可能失去同步(net.burp) ,慢服务器等...)。

答案 3 :(得分:-1)

在这种情况下,远程休息服务需要基本身份验证。我每次通过循环时都会发送不同的用户名和密码。我终于意识到基本的身份验证凭据在服务器端缓存了。

在服务器端,如果服务找到名为JSESSIONID的有效cookie,则会忽略http请求标头中的Basic Auth用户名和密码。

所以,解决方案是使用Jquery cookie插件并确保为每个请求删除JSESSIONID,如下所示:

$.cookie('JSESSIONID', null {path: '/pathToCookie'});