Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
232 views
in Technique[技术] by (71.8m points)

javascript - How to link XMLHTTP Request to right Response in case of multiple AJAX request in a loop

I am trying to send multiple AJAX request inside a for loop. I need to make sure that responses are getting linked to the right request that are being made. I am following the solution that is posted here XMLHttpRequest in for loop Here, fileBatches is the size of the loop. I am trying to capture the response which says the information about the number of requests succeeded and failed and trying to store it in _finalResponseArray. If the length of the fileBatches is 3, there are chances that first request may take more time than other request. Consider first request, takes sometime to process and by the time, second request and third request would have completed and then first request would complete. I need to make sure that right request is getting linked to right response. Here when the first loop starts(i=0), it takes sometime to get processed and by the time second loop starts (i=1) and gets processed. XHR[i].readyState == 4 (since i has incremented 1 and how to get the value of i = 0?) gets confused and I am not able to get the response linked to the right request. Please find the code below. Below function gets executed for multiple AJAX request.

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

I am not sure what I am making wrong here, but the requests are not getting linked to correct responses and they randomly gets added to _finalResponseArray. It works perfectly if there is only one request without any loop. How to make sure that onreadystatechange is verified for correct loop?

**********Updates

Tried solution as suggested in comments and also various other approaches (referring past questions in stack overflow):

Even though I try to use closures, response messes up. For all 3 requests, it randomly picks a response and produces same response for all 3 requests.

Should my request have something unique so that response can track it correctly. I do see the iterator value 'i' was appended to URL when we try to send ant GET or POST request, but I am just sending same URL for different requests. Does that matter?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Firstly, I'd recommend using so called XMLHttpRequest 2.0 - rather than the fiddly onreadystatechange stuff, just use onload and onloadend (you'll see why the latter in the code below)

Due to the asynchronous nature of XMLHttpRequest you can't predict when the requests are all done, so _finalResponseArray will only be complete once the final onloadend is complete

Adding a count of complete requests will allow you to do whatever you need in the onloadend callback once all requests have finished. onloadend is called regardless of success or failure

I also use .forEach instead of IIFE

var fileBatches = "Calling a function which returns array of values that needs to be processed"
var _done = 0;
var _count = fileBatches.length;
var _finalResponseArray = [];

fileBatches.forEach(function(item, i) {
    var finalBatch = []
    var xhr = new XMLHttpRequest();
    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.open('POST', theURL);
    xhr.onload = function (event) {
        if (xhr.status == 200) {
            _finalResponseArray[i] = (xhr.responseText);
        }         
    };
    xhr.onloadend = function (event) {
        // this gets called in ALL cases, i.e. after load, error or abort
        if(++_done == _count) {
            // _finalResponseArray is complete here
        }
    };
    xhr.setRequestHeader('accept', 'text/JSON');
    xhr.send(finalData);
});
//_finalResponseArray will ALWAYS be empty here

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...