繁体   English   中英

javascript-XMLHttpRequest如何发送多个同时请求?

[英]Javascript - XMLHttpRequest how to send multiple simultaneous requests?

我遇到一个非常自然的问题。 我正在尝试实现一个购物车,借此在客户端存储了Cookie,以识别已订购哪些商品的ID及其数量。 当我加载结帐HTML页面时,我正在读取cookie并一个接一个地获取商品ID。 然后对于每个项目ID,我都会将请求发送到我的servlet,该servlet将返回信息。 为了简化操作,我将多余的行截断了:

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

问题在这里

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

如果我将请求类型更改为SYNCHRONOUS通信,即从TRUE更改为FALSE,则一切正常,但是如您所知,网页将必须等待服务器处理每个项目。 因此,网页将发送对项目84234的请求,等待,当有响应时,然后发送对项目84239的请求,等等。

据我所知,如果我改回ASYNCHRONOUS XMLHttpRequest,除了/仅当arrXhr [ItemToProcess] .readyState == 1时,什么都不会发生。 但是对于其他2、3、4(其中4个是最重要的州)而言,它们永远不会被触发。

知道为什么吗? 最重要的是,我们如何克服这个问题? 我知道XMLHttpRequest在单独的线程上工作,这很可能是问题所在,但我找不到解决方案。

我的目标很简单,我希望我的网页在从磁盘上的cookie读取后立即将多个请求同时发送到我的servlet。 因此,对于每个Cookie,我想发送请求并希望以异步方式接收响应。 我不希望浏览器在最终请求完成之前一直等待。 因此,如果您有任何其他想法/实现,我可以是一个非常开放的人;)

ps我正在使用TomCat 7

如下所示:

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

您必须使用“ this”代替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
        }  
   }

我强烈建议您使用事件监听器,以防您愿意使用异步处理。

请注意,由于对用户体验的负面影响,Gecko 30.0(Firefox 30.0等)不赞成使用同步请求。

这个(理解事件监听器)当然是异步的,并在响应到达时立即对其进行处理。

到目前为止,就绪状态更改可能会带来很多并发症和头痛。 当您要处理多个响应并且响应处理的顺序很重要时,尤其如此。

当您要在响应到达时对其进行处理时,有一种简单的方法可以将EventListener添加到每个请求中。

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

...

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

...您甚至可以自定义要处理的状态。 这些是当前允许的响应状态:

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

不必为每个产品ID发送多个同时请求,而是将所有ID包装到一个数组中,进行序列化并仅使用一个请求。

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

通过请求仅发送serializedIds变量

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM