开发者

Javascript - XMLHttpRequest how to send multiple simultaneous requests?

开发者 https://www.devze.com 2023-04-09 10:51 出处:网络
I\'m encountering a very paranormal problem. I\'m trying to implement a shopping cart, whereby I have cookies stored on the client side to identify which items\' ID have been ordered and their quantit

I'm encountering a very paranormal problem. I'm trying to implement a shopping cart, whereby I have cookies stored on the client side to identify which items' ID have been ordered and their quantities. When I load the checkout HTML page, I'm reading the cookies and getting the item id one after the other; then for each item id I ll be sending the request to my servlet which would return the information. I have truncated redundant lines to keep it simple to follow:

 var arrXhr = new Array();
 function ProcessCheckout(){
        try
        {
            var myArr = new Array();
            myArr[0]=84234;
            myArr[1]=84239;
            myArr[2]=84240;

            for (var intLoop=0; intLoop < myArr.length; intLoop++){
                var intIcint=myArr[intLoop]; 

                arrXhr[intIcint]= new XMLHttpRequest();
                function Populate_CheckOutCart(){
                arrXhr[intIcint].open('POST', strRemoteUriReq, true);                         
                arrXhr[intIcint].send(null);                                       
                arrXhr[intIcint].onreadystatechange= ProcessSrvRsp(intIcint);
            }
        }catch(errors)
           {
              alert(errors.message);
           }
     }
 }

       function ProcessSrvRsp(ItemToProcess){
            if (arrXhr[ItemToProcess].readyState==4){   
                //doing some functionality here on item code: ItemToProcess
             }  
       }

The problem here is in line

arrXhr[intIcint].open('POST', strRemoteUriReq, true);  

If I change the request type to SYNCHRONOUS communication, i.e. from TRUE to FALSE, everything works correctly, but as you know the web page will have to wait for the server to process every item. Hence, the web page will send a request for item 84234, waits, when there is a response then sends a request for item 84239, etc..

From my knowledge, if I change back ASYNCHRONOUS XMLHttpRequest, nothing happens except/only when arrXhr[ItemToProcess].readyState==1. But as regards the other states, 2,3,4 (4 being the most important to start working with), they are never triggered.

Any idea why? And most import开发者_运维知识库antly how can we overcome this? I'm aware that the XMLHttpRequest works on a separate thread and most probably this is the issue, but I can't figure out a solution.

My objective is simple, I want my web page to send multiple requests to my servlet simultaneously as soon as it is reading from the cookies on the disk; hence for each cookie I want to send a request and expect to receive a response in an asynchronous way. I don't want the browser stuck waiting until the final request has been completed. So, if you have any other idea/implementation, I can be a very open minded person ;)

p.s. I'm using TomCat 7


Something like next:

function ProcessCheckout() {
    var arrXhr=[];
    var myArr=[];
    myArr.push(84234);
    myArr.push(84239);
    myArr.push(84240);

    var helperFunc=function(arrIndex,itemId) {
      return function() {
        if(arrXhr[arrIndex].readyState===4) {
          //doing some functionality here on item
          ProcessResponseForItem(arrIndex,myArr,arrXhr);
          // doing some code if all xhr's is completed
          ProcessResponseForAllItems(myArr,arrXhr);
        }
      }
    }

    for(var i=0; i<myArr.length; i++) {
      var itemId=myArr[i]; 
      arrXhr[i]=new XMLHttpRequest();
      arrXhr[i].open('POST', strRemoteUriReq, true);
      arrXhr[i].onreadystatechange=helperFunc(i,itemId);
      arrXhr[i].send(/*some item data sended to server for item with id itemId*/);
    }
 }

 function ProcessResponseForItem(arrIndex,myArr,arrXhr) {
   if(arrXhr[arrIndex].status===200) {
     // do some code if response is succ
   }
   else {
     // if fail
   }
 }

 function ProcessResponseForAllItems(myArr,arrXhr) {
   var i,isAllComplete=true,isAllCompleteSucc=true;
   for(i=0;i<myArr.length;i++) if((!arrXhr[i])||(arrXhr[i].readyState!==4)) {
     isAllComplete=false;
     break;
   }
   if(isAllComplete) {
     for(i=0;i<myArr.length;i++) if(arrXhr[i].readyState!==200) {
       isAllCompleteSucc=false;
       break;
     }
     if(isAllCompleteSucc) {
       // do some code when all is completed and all is succ
     }
     else {
       // do some code when all is completed and some is fail
     }
   }
 }


I'd strongly suggest using the Event Listeners in case You're willing to use asynchronous processing.

Note that Gecko 30.0 (Firefox 30.0 etc.) deprecated the synchronous requests due to negative impact on user's experience.

This (understand Event Listener) is of course asynchronous and processes the responses as soon as it arrives.

So far the onreadystatechange could bring a lot of complications and headaches. This is especially true when You're handling more than one responses and the order of the response processing matters.

When You want to process the responses as it arrives there is a simple way to add EventListener to each of the requests.

arrXhr[intIcint].open('POST', strRemoteUriReq, true);                         
arrXhr[intIcint].addEventListener("load", processResponse);
arrXhr[intIcint].send(null);                                       

...

function processResponse() {
  console.log("Response arrived.");
}

... You can even customize the state You're going to process. These are the currently allowed states of response:

arrXhr[intIcint].addEventListener("progress", updateProgress);
arrXhr[intIcint].addEventListener("load", transferComplete);
arrXhr[intIcint].addEventListener("error", transferFailed);
arrXhr[intIcint].addEventListener("abort", transferCanceled);


You have to use "this" instead arrXhr[intIcint]

var arrXhr = new Array();
 function ProcessCheckout(){
    try
        {
            var myArr = new Array();
            myArr[0]=84234;
            myArr[1]=84239;
            myArr[2]=84240;

            for (var intLoop=0; intLoop < myArr.length; intLoop++){
                var intIcint=myArr[intLoop]; 

                xhr= new XMLHttpRequest();
                function Populate_CheckOutCart(){
                xhr.open('POST', strRemoteUriReq, true);                         
                xhr.send(null);                                       
                xhr.onreadystatechange= ProcessSrvRsp();
                // or   xhr.addEventListener("load", ProcessSrvRsp);

            }
        }catch(errors)
           {
              alert(errors.message);
           }
     }
 }

    function ProcessSrvRsp(){
        if (this.readyState==4){   
            //doing some functionality here on item code: this
        }  
   }


instead of sending multiple simultanous requests for each product id, wrap all the ids into an array, serialize it and use only one request.

var ids = [1, 2, 3];
var serializedIds = ids.join('|'); // serializedIds = '1|2|3';

send only the serializedIds variable through the request

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号