在Ajax的回调中 使用setTimeout再次请求 造成的问题。50分求分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Ajax的回调中 使用setTimeout再次请求 造成的问题。50分求分析相关的知识,希望对你有一定的参考价值。

上面是Chrome调试工具的控制台log,出现问题的代码如下:
function checkComments()
console.log("in checkComments");
if(!oXHR)
oXHR = JSSTU.AJAX.createXHR();
else if(0!=oXHR.readyState)
oXHR.abort();

oXHR.open("get","CheckComments.inc",true);
JSSTU.EventUtil.addHandler(oXHR,"readystatechange",function()
if(4==oXHR.readyState)
if((oXHR.status>=200&&oXHR.status<300)|| 304==oXHR.status)
var dataArray = oXHR.responseText.split("||");
if(iLastCommentId!=dataArray[0])
iLastCommentId = dataArray[0];
if(-1!=iLastCommentId)
showNotification(dataArray[1],dataArray[2]);


console.log("in setTimeout");
setTimeout(checkComments,iInterval);


);
oXHR.send(null);

这段我以每1秒一次的间隔去检查服务器上的数据是否更新,现在的问题是,第一秒这段代码会请求一次,第二秒请求2次,第三秒请求4次,不断以2的倍数递增很快会到达每秒请求数千次把自己卡死。

出现问题后我追踪了一晚上,这段代码类似的方法我经常用,比如我在
/**
* 预加载下一页
*/
function loadNextPage()
if(iNextPageToLoad<=iPageCount)
if(!oXHR)
oXHR = JSSTU.AJAX.createXHR();
else if(0!=oXHR.readyState)
oXHR.abort();

oXHR.open("get", getURLForPage(iNextPageToLoad)+"&dataonly=true",true);
JSSTU.EventUtil.addHandler(oXHR,"readystatechange",function()
if(4==oXHR.readyState)
if((oXHR.status>=200&&oXHR.status<300)|| 304==oXHR.status)
var divLoadArea = document.getElementById("divLoadArea");
divLoadArea.innerhtml = oXHR.responseText;
var divNewPage = document.getElementById("divPage"+iNextPageToLoad);
divNewPage.style.display = "none";
document.body.appendChild(divNewPage);
divLoadArea.innerHTML = "";
iNextPageToLoad++;
setTimeout(loadNextPage,iWaitBeforeLoad);


);
oXHR.send(null);


中不断预加载当前书页的后续页,这样不会出现问题,很稳定的以iWaitBeforeLoad毫秒间隙请求一次。

这两段代码几乎是一样的,为什么会造成两种不同的情况.
需要指出的是,如果出现问题那段回调函数,我把它分离到外面写成一个独立的函数function handle()...
再使用它来处理JSSTU.EventUtil.addHandler(oXHR,"readystatechange",handle);
则一切正常,求分析第一段代码造成雪崩式请求的原因。
JSSTU这些是自己封的库,平时一直在使用,都挺正常的。
如果需要其他详细信息可以留言
代码下载地址
https://c9.io/xoozi/jsstu/workspace/php/www.zip

参考技术A 因为不清楚你那个JSSTU.EventUtil.addHandler怎么实现的,所以不好分析。

但是给你提几个建议:
1.不要重用XHR对象。
2.用比较完善的类库,比如jquery,里面的promise结构用起来比这个简单。
3.用setInterval来做循环处理的任务。追问

addHandler:function(element,type,handler)

if(element.addEventListener)
element.addEventListener(type,handler,false);
else if(element.attachEvent)
element.attachEvent("on"+type,handler);
else
element["on"+type]=handler;

参考技术B 你描述的情况像是使用setInterval。造成的。
而且这种事情用setInterval再最外面调用一次就好了。
你这样递归是怕有的没有返回就开始重新发送?追问

对处理完再SetTimeout就是为了处理完一次再请求,而不是单纯为了循环。

100分求分析的原因,就是因为问题中的两段代码第一段会出问题,而第二段很正常。
两段我比较了很久,都觉得几乎是一样的。

我主要想知道为什么,至于解决方案倒不重要,按我所说把onreadystatechange回调那段,分离到外面一个独立函数里都可以解决。

https://c9.io/xoozi/jsstu/workspace/php/www.zip 这里可以下载到代码,内附说明文本

追答

其实也不一定是这段代码的问题,如果代码二没问题,一也应该没问题,是不是多次调用了方法。

形成类似死循环了啊。检查下是否有这种地方。

这个代码我也没法调,不知道该怎么下手啊。
如果没有以上说的情形。建议先把代码做到最简(只保留必要的逻辑,业务部分先不要),然后看能不能正常跑。
不停的删减不同部分的代码,看看那段代码引起的问题。找到问题出在哪儿。

追问

我也是做了很多尝试,至少有2种办法解决了这个问题,一是单独把onreadystatechange回调提到外面的函数里,另一是直接用oXHR.onreadystatechange来设置回调。

我只是想知道为什么代码一有问题,代码二没问题。

追答

通常这种问题的根都是很简单,由很低级的错误原因造成的。
可不可能是你的浏览器最近装了什么插件,造成你的ajax请求会发两遍,然后就有2个返回。
这样就有可能造成会2次调用onreadystatechange方法。

追问

插件在前段时间已经全部禁用了,这个奇怪的是2份类似代码跑出来结果不一样

追答

不清楚了,你现在运行这2段代码还有差别?有的话,就整个慢慢比较,这个就是一个调试的过程,慢慢调吧。其实既然解决了也可以不管。

javascript中setTimeout每隔1秒调用一次ajax,但回调函数只调用一次。求解。。

部分代码如下: function getUsers()//查询所有在线用户
var url="chat-room?"+Math.random();
httprequest.onreadystatechange=userlist;
httprequest.open("get",url,true);
httprequest.send(null);


function userlist()
if(httprequest.readyState==4)
if(httprequest.status==200)
var s=httprequest.responseText;
//由此得到所有在线用户




第一次没问题,我今天忙了一天之这个了,我每一秒查询一下在线的用户,但第一次行。其他用户下线后,查询到了,但返回不到回调函数上。
刚有人指点我一下,就是在回调函数里调用getusers(),不用那个timer,等明天我试试。

还有发送消息时 定义url="sendmessage?message='房价的快速路附近'&touserid=1000"
总出现中文乱码,请问有什么好的办法?

参考技术A function getUsers()//查询所有在线用户
var url="chat-room?"+Math.random();
httprequest.onreadystatechange=userlist;
httprequest.open("get",url,true);
httprequest.send(null);
window.setTimeout(getUsers,1000)
追问

function timer()
getUsers();
setTimeout("timer()",1000);

我已经有timer了
可以不断的查询了,但只执行一次回调函数

追答

httprequest.open("get",url,false);//改成同步执行看看!

追问

试过了,不行

参考技术B 这个不大懂哦 参考技术C 看不懂55 参考技术D 你得到第一次正确的结果了么? 第5个回答  2011-09-01 把代码贴全了再说,你是想做AJAX长轮询吧?本回答被提问者采纳

以上是关于在Ajax的回调中 使用setTimeout再次请求 造成的问题。50分求分析的主要内容,如果未能解决你的问题,请参考以下文章

回调函数的使用场合

javascript中setTimeout每隔1秒调用一次ajax,但回调函数只调用一次。求解。。

回调而不是 setTimeout

使用 Node 进行 Jest 测试 - 超时 - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调

如何在 ajax 回调中重置表单?

ajax怎样再次执行?