不同时发起的双重AJAX请求

3

好的,我正在尝试制作一个AJAX聊天系统,每400毫秒轮询一次聊天数据库。这部分是工作正常的,但活跃用户列表不行。当我尝试合并这两个请求时,前两个请求会被执行,然后整个过程就会失控,通常定时(12秒)的活跃用户列表请求会开始以每1毫秒更新一次,而第一个请求永远不会再次发生。下面是两个请求的完整AJAX代码:

var waittime=400;chatmsg=document.getElementById("chatmsg");
room = document.getElementById("roomid").value; 
chatmsg.focus()
document.getElementById("chatwindow").innerHTML = "loading...";
document.getElementById("userwindow").innerHTML = "Loading User List...";
var xmlhttp = false;
var xmlhttp2 = false;
var xmlhttp3 = false;
function ajax_read(url) {
if(window.XMLHttpRequest){
    xmlhttp=new XMLHttpRequest();
    if(xmlhttp.overrideMimeType){
        xmlhttp.overrideMimeType('text/xml');
    }
} else if(window.ActiveXObject){
    try{
        xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e) {
        try{
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        } catch(e){
        }
    }
}
if(!xmlhttp) {
    alert('Giving up :( Cannot create an XMLHTTP instance');
    return false;
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState==4) {
    document.getElementById("chatwindow").innerHTML = xmlhttp.responseText;
    setTimeout("ajax_read('methods.php?method=r&room=" + room +"')", waittime);
    }
}
xmlhttp.open('GET',url,true);
xmlhttp.send(null);
}
function user_read(url) {
if(window.XMLHttpRequest){
    xmlhttp3=new XMLHttpRequest();
    if(xmlhttp3.overrideMimeType){
        xmlhttp3.overrideMimeType('text/xml');
    }
} else if(window.ActiveXObject){
    try{
        xmlhttp3=new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e) {
        try{
            xmlhttp3=new ActiveXObject("Microsoft.XMLHTTP");
        } catch(e){
        }
    }
}
if(!xmlhttp3) {
    alert('Giving up :( Cannot create an XMLHTTP instance');
    return false;
}
xmlhttp3.onreadystatechange = function() {
if (xmlhttp3.readyState==4) {
    document.getElementById("userwindow").innerHTML = xmlhttp3.responseText;
    setTimeout("ajax_read('methods.php?method=u&room=" + room +"')", 12000);
    }
}
xmlhttp3.open('GET',url,true);
xmlhttp3.send(null);
}
function ajax_write(url){
if(window.XMLHttpRequest){
    xmlhttp2=new XMLHttpRequest();
    if(xmlhttp2.overrideMimeType){
        xmlhttp2.overrideMimeType('text/xml');
    }
} else if(window.ActiveXObject){
    try{
        xmlhttp2=new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e) {
        try{
            xmlhttp2=new ActiveXObject("Microsoft.XMLHTTP");
        } catch(e){
        }
    }
}
if(!xmlhttp2) {
    alert('Giving up :( Cannot create an XMLHTTP instance');
    return false;
}
xmlhttp2.open('GET',url,true);
xmlhttp2.send(null);
}
function submit_msg(){
nick = document.getElementById("chatnick").value;
msg = document.getElementById("chatmsg").value;
document.getElementById("chatmsg").value = "";
ajax_write("methods.php?method=w&m=" + msg + "&n=" + nick + "&room=" + room + "");
}
function keyup(arg1) { 
if (arg1 == 13) submit_msg(); 
}
var intUpdate = setTimeout("ajax_read('methods.php')", waittime);
var intUpdate = setTimeout("user_read('methods.php')", waittime);

这几乎像迷信一样,但我在并发的XMLHttpRequests(尤其是在IE中)方面运气不佳。 - Pointy
是的,我宁愿不使用并发请求,但我不知道其他实现这个目标的方法。 - Nik
也许可以尝试使用不同的等待时间来偏移这两个请求? - Banjer
2
var waittime=400; chatmsg=…; 中使用逗号代替分号,这样 chatmsg 就成为全局变量了。其他全局变量也是如此(使用 var)。 - Marcel Korpel
曾经有一个逗号,也有不同的等待时间,但它仍然像滚雪球一样变得更大。 - Nik
1个回答

2
问题在于在user_read中设置了一个定时器,在12秒后运行ajax_read,并带有正确的URL。因此,当调用此ajax_read时,它会获取信息并设置一个新的超时时间,这次在waittime之后调用ajax_read,带有?method=r…。因此,在user_read的第一个超时之后,它永远不会再次被调用。
FYI,我使用(Firebug的Net面板和本地Web服务器上的虚假表单和methods.php)进行观察。将waittime设置为4000并使用.innerHTML += …,每4秒钟会产生两个调用。 index.html(我知道,它很快又脏):
<!DOCTYPE html>
<html>
 <head>
  <meta charset=UTF-8>
  <title>Chat</title>
 </head>
 <body>
  <input id="chatnick" type="text" value="Nickname"><br>
  <input id="roomid" type="text" value="4"><br>
  <input id="chatmsg" type="text"><br>
  <div id="userwindow" style="width: 500px; height: 300px"></div><br>
  <div id="chatwindow" style="width: 300px; height: 300px"></div><br>
  <script src="js.js"></script>
 </body>
</html>

虚假的methods.php文件:

blah<br>

请注意xmlhttp.status可能不是200


1
@Nik - 当我更正了那个函数调用并将waittime设置回400时,使用本地Web服务器一切似乎都运行正常。我不知道在较慢的连接下,在有如此多的请求的真实世界情况下会发生什么,但我不想给自己公司的服务器带来太大的负载。顺便说一句,我认为你可以重构一下你的代码:将一个字符串传递而不是一个函数引用传递给setTimeout不是一个好主意(速度慢且大多数情况下是不必要的),而且将XMLHttpRequest代码复制三次也不高效。 - Marcel Korpel
@Nik - 只需按照我的答案创建文件,您就可以进行测试,例如使用Firebug。而且您实际上是将字符串传递给setTimeout,例如"ajax_read('methods.php?method=r&room=" + room +"')"。函数引用不应该被引号包围:setTimeout(ajax_read, 400);。这样,您无法将参数传递给ajax_read,因此您应该找到另一种实现所需功能的方法。这样更有效率。顺便说一下,您是否检查了发送到服务器的那些变量(如msgroom)是否包含恶意代码? - Marcel Korpel
是的,PHP文件在接收每个变量时都会进行检查、转义和验证,如果发现任何不喜欢的内容,它就会终止请求。我只需要将xmlhttp.open设置为包含字符串的URL吗? - Nik
@Nik - 你的意思是在setTimeout函数内部吗?是的,我不知道为什么它不应该。 - Marcel Korpel
那么,如果我通过setTimeout设置它而不是xmlhttp.open,为什么它会不安全呢? - Nik
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接