如何在循环中发出多个AJAX请求时将XMLHTTP请求链接到正确的响应

时间:2017-05-22 01:06:12

标签: javascript ajax asynchronous xmlhttprequest

我正在尝试在for循环中发送多个AJAX请求。我需要确保响应与正在进行的正确请求相关联。我正在关注此处发布的解决方案XMLHttpRequest in for loop 这里,fileBatches是循环的大小。我正在尝试捕获响应,该响应表示有关请求数量成功和失败的信息,并尝试将其存储在_finalResponseArray中。如果fileBatches的长度为3,则第一个请求可能比其他请求花费更多时间。考虑第一个请求,需要一些时间来处理,到时候,第二个请求和第三个请求将完成,然后第一个请求将完成。我需要确保正确的请求与正确的响应相关联。这里,当第一个循环开始(i = 0)时,需要一些时间来处理,并且在第二个循环开始(i = 1)时进行处理。 XHR [i] .readyState == 4(因为我增加1并且如何获得i = 0的值?)变得混乱,我无法将响应链接到正确的请求。请在下面找到代码。下面的函数被执行多个AJAX请求。

var XHR = [];
var fileBatches = "Calling a function which returns array of values that needs to be processed"
var _finalResponseArray = [];
for (var i = 0; i < fileBatches.length; i++) 
{
   (function(i)
    {
      finalBatch = []
      finalBatch.push("Things that need to be processed by controller");

      finalData = finalBatch.join('&').replace(/%20/g, '+'); // Sending the values in a format so that it will be received by controller

      XHR[i] = new XMLHttpRequest();

      console.log(i);   

      XHR[i].open('POST', theURL);

      XHR[i].onreadystatechange = function (event) 
        {
          console.log("Here");
          if (XHR[i].readyState == 4) 
          {              
            console.log("This request is complete");
            console.log("I value is " + i);
          if (XHR[i].status == 200) 
          {
            _finalResponseArray.push(XHR[i].responseText);
            console.log("Inside" + _finalResponseArray);
          }         
        }
    }

    XHR[i].setRequestHeader('accept', 'text/JSON');

    XHR[i].send(finalData);
    })(i);
}

我不确定我在这里做错了什么,但请求没有与正确的响应相关联,而是随机添加到_finalResponseArray。如果只有一个请求没有任何循环,它可以完美地工作。如何确保onreadystatechange被验证是否正确循环?

**********更新

按照评论和其他各种方法(在堆栈溢出中引用过去的问题)中的建议尝试了解决方案:

即使我尝试使用闭包,反应也会变得混乱。对于所有3个请求,它会随机选择一个响应并为所有3个请求生成相同的响应。

我的请求是否应该有独特的内容,以便响应可以正确跟踪它。当我们尝试发送ant GET或POST请求时,我确实看到迭代器值'i'被附加到URL,但我只是为不同的请求发送相同的URL。那有关系吗?

2 个答案:

答案 0 :(得分:2)

首先,我建议使用所谓的#! - 而不是繁琐的onreadystatechange内容,只需使用XMLHttpRequest 2.0onload(您将在下面的代码中看到后者的原因) )

由于onloadend的异步性质,您无法预测请求何时全部完成,因此XMLHttpRequest只有在最终_finalResponseArray完成后才会完成

添加完整请求数将允许您在所有请求完成后在onloadend回调中执行所需操作。无论成功与否,都会调用onloadend

我也使用onloadend代替IIFE

.forEach

答案 1 :(得分:1)

您可能希望将onreadystatechange函数逻辑拉入其自己的函数定义中,以便它可以在本地管理范围。试试这个:

var XHR = [];
var _finalResponseArray = [];

var createReadyStateChangeCb = function(responseIdx)
{
    return function(event)
    {
        console.log("Here");
        if (XHR[responseIdx].readyState == 4) 
        {              
          console.log("This request is complete");
          console.log("I value is " + responseIdx);
          if (XHR[responseIdx].status == 200) 
          {
            _finalResponseArray.push(XHR[responseIdx].responseText);
            console.log("Inside" + _finalResponseArray);
          }
        }
    }
}

for (var i = 0; i < fileBatches.length; i++) 
{
   (function(i)
    {
      finalBatch = []
      finalBatch.push("Things that need to be processed by controller");

      finalData = finalBatch.join('&').replace(/%20/g, '+'); // Sending the values in a format so that it will be received by controller

      XHR[i] = new XMLHttpRequest();

      console.log(i);   

      XHR[i].open('POST', theURL);

      XHR[i].onreadystatechange = createReadyStateChangeCb(i);
    }

    XHR[i].setRequestHeader('accept', 'text/JSON');

    XHR[i].send(finalData);
    })(i);
}