Javascript - XMLHttpRequest, как отправить несколько одновременных запросов? - PullRequest
2 голосов
/ 29 сентября 2011

Я столкнулся с очень паранормальной проблемой.Я пытаюсь внедрить корзину покупок, в которой у меня на стороне клиента хранятся файлы cookie, чтобы определить, какие идентификаторы товаров были заказаны и их количество.Когда я загружаю HTML-страницу оформления заказа, я читаю файлы cookie и получаю идентификатор элемента один за другим;затем для каждого идентификатора элемента я буду отправлять запрос в мой сервлет, который будет возвращать информацию.Я сократил избыточные строки, чтобы было проще следовать:

 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 наЛОЖЬ, все работает правильно, но, как вы знаете, веб-странице придется ждать, пока сервер обработает каждый элемент.Следовательно, веб-страница отправит запрос на элемент 84234, ожидает, когда ответ поступит, затем отправляет запрос на элемент 84239 и т. Д.

Насколько мне известно, если я вернусь обратно ASYNCHRONOUS XMLHttpRequest, ничего не происходиткроме / только когда arrXhr [ItemToProcess] .readyState == 1.Но что касается других штатов, 2,3,4 (4 является наиболее важным для начала работы), они никогда не запускаются.

Есть идеи почему?И самое главное, как мы можем преодолеть это?Я знаю, что XMLHttpRequest работает в отдельном потоке, и, скорее всего, это проблема, но я не могу найти решение.

Моя цель проста, я хочу, чтобы моя веб-страница отправляла несколько запросовна мой сервлет одновременно, как только он читает файлы cookie на диске;следовательно, для каждого файла cookie я хочу отправить запрос и получить ответ асинхронно.Я не хочу, чтобы браузер застрял в ожидании, пока окончательный запрос не будет выполнен.Так что, если у вас есть другие идеи / реализации, я могу быть очень открытым человеком;)

ps Я использую TomCat 7

Ответы [ 4 ]

4 голосов
/ 29 сентября 2011

Примерно так:

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
     }
   }
 }
1 голос
/ 26 июля 2017

Вы должны использовать «это» вместо 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
        }  
   }
0 голосов
/ 28 июня 2017

Я настоятельно рекомендую использовать прослушиватели событий на тот случай, если вы захотите использовать асинхронную обработку.

Обратите внимание, что Gecko 30.0 (Firefox 30.0 и т. Д.) Устарели синхронные запросы из-за негативного влияния на опыт пользователя.

Это (понимаем, слушатель событий), конечно, асинхронный и обрабатывает ответы, как только он приходит.

До сих пор onreadystatechange мог принести много осложнений и головных болей. Это особенно верно, когда вы обрабатываете более одного ответа, и порядок обработки ответа имеет значение.

Если вы хотите обрабатывать ответы по мере их поступления, есть простой способ добавить 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);
0 голосов
/ 29 сентября 2011

вместо отправки нескольких одновременных запросов для каждого идентификатора продукта, оберните все идентификаторы в массив, сериализуйте его и используйте только один запрос.

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

отправлять только переменную serializedIds через запрос

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...