日期:2014-05-16  浏览次数:20916 次

(转)实现Ajax请求队列按顺序执行
摘自http://www.ilovejs.net/archives/163
之前想做一个Web桌面的项目,考虑的必须得使用Ajax请求队列,使得Ajax的请求能按照队列按顺序执行,解决了Ajax异步传输覆盖的问题,也看了几个别人的代码,都整不太明白,所以自己干脆自己搞搞阵,自己实现,也得个安慰奖。我的实现方法很简单,通过递归调用函数,而无需使用定时器去检查Ajax请求是否已经执行完毕,具体的例子请看下面的代码:
Javascript:

onload = function(){
  document.getElementById("btn").onclick = function(){
    //添加请求队列
  addAjax({method: "GET",url: "test2.txt",callback: callback1});
  addAjax({method: "GET",url: "test.txt",callback: callback2});
  addAjax({method: "GET",url: "test2.txt",callback: callback3});
    //开始执行队列
    executeAjax();
  }
}
var callback1 = function(data, xhr){
  document.getElementById("div1").innerHTML = data;
}
var callback2 = function(data, xhr){
  document.getElementById("div2").innerHTML = data;
}
var callback3 = function(data, xhr){
  document.getElementById("div3").innerHTML = data;
}


HTML:

<div id="div1">getStyle test.</div>
<div id="div2">getStyle test.</div>
<div id="div3">getStyle test.</div>
<input type="button" value="Get data" id="btn" />


这三个请求会按顺序执行下来,请点击查看具体效果

下面展示我所实现这个请求队列的Javascript源码:

var ajaxes = []; //用于存储参数对象的队列
//用于声明XMLHttpRequest实例对象
var Xhr = function(){
  var xhr = false;
  try {
    xhr = new XMLHttpRequest();
  }
  catch (e) {
    try {
      xhr = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
      xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
  return xhr;
}
var xhr = new Xhr(); //获得XMLHttpRequest实例对象xhr
//executeAjax是主要的执行Ajax的函数
var executeAjax = function(){
  //如果队列为空,则退出执行
  if (!ajaxes.length)
  return;
  var options = ajaxes[0];
  if (xhr) {
    xhr.open(options.method, options.url, true);
    xhr.onreadystatechange = function(){
      if (xhr.readyState === 4 &amp;&amp; (xhr.status === 200 || xhr.status === 304)) {
        options.callback(xhr.responseText, xhr);
        //删除队列中的第一个请求
        ajaxes.shift();
        //如果队列中还有请求,就接着递归执行executeAjax函数,直到队列为空
        if (ajaxes.length > 0) {
          executeAjax();
        }
      }
    }
    if (xhr.method === "post") {
      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    }
    xhr.send(options.data || null);
  }
}
//用于添加队列的函数
var addAjax = function(options){
  ajaxes.push(options);
}

上面写的或许有些人会认为封装性不好,污染全局变量,如果封装起来也是非常简单的,这只是本人实现了这个效果时候的草稿,放到具体的项目中当然会封装为类或者对象,方便调用,具体的封装后的代码就不提供了。

另外看上面大虾写的代码时也学习了另外一点

使用Ajax提交的参数多是些简单的字符串,可以直接使用GET方法将要提交的参数写到open方法的url参数中,此时send方法的参数为null。
    例如 :
    var url = "login.jsp?user=XXX&pwd=XXX";
                 xmlHttpRequest.open("GET",url,true);
                 xmlHttpRequset.send(null);

       此外,也可以使用send方法传递参数。使用send方法传递参数使用的是POST方法,需要设定Content-Type头信息,模拟HTTP POST方法发送一个表单,这样服务器才会知道如何处理上传的内容。参数的提交格式和GET方法中url的写法一样。设置头信息前必须先调用open方法。
       例如:
     xmlHttpRequest.open("POST","login.jsp",true);
     xmlHttpRequest.setRequestHeder("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
     xmlHttpRequest.send("user="+username+"&pwd="+password);

需要注意的是根据提交方式的不同,两种提交方式分别调用后台的doGet方法和doPost方法。
下面有人的总结摘录下
引用

学习的过程中发现几点:

1 Url不能使用其它domain, 比如用了http://www.google.cn/xxx.html, 结果提示没有权限使用 XMLHttpRequest.open();
2 XMLHttpRequest.send() 必须带参, 如果没有可以使用 XMLHttpRequest.send(null);
3 XMLHttpRequest.open(method, url, flag) 如果flag==false, 则不回调 XMLHttpRequest.onreadystatechange;