我遇到了一个非常超自然的问题。我正在尝试实施购物车,我在客户端存储了Cookie,以确定订购了哪些商品的ID及其数量。当我加载结帐HTML页面时,我正在读取cookie并逐个获取项目ID;然后对于每个项目ID,我将向我的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,并希望以异步方式接收响应。我不希望浏览器在最终请求完成之前等待。所以,如果你有任何其他想法/实施,我可以是一个非常开放的人;)
P.S。我正在使用TomCat 7
答案 0 :(得分:4)
接下来的事情:
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 :(得分:1)
你必须使用“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
}
}
答案 2 :(得分:0)
如果您愿意使用异步处理,我强烈建议您使用事件监听器。
请注意,由于对用户体验的负面影响,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);
答案 3 :(得分:-1)
而不是为每个产品ID发送多个同时请求,将所有ID包装到一个数组中,将其序列化并仅使用一个请求。
var ids = [1, 2, 3];
var serializedIds = ids.join('|'); // serializedIds = '1|2|3';
通过请求
仅发送serializedIds变量