你的位置:首页 > Java教程

[Java教程]浅析XMLHttpRequest


在Ajax技术出现之前,客户端浏览器与服务器之间的交互是非常传统的方式,每一次,浏览器向服务器发送一个请求,服务器接受并处理,返回相对应的处理结果给浏览器,浏览器接收服务器的返回结果,重新加载新的结果,这样的交互方式方式,用户需要花费一定的时间来每一次等待页面的重新加载,以求获取服务器的响应,如果网络不给力或者加载的对象比较大,需要花费一定的时间,那么,用户就并需花费大量的时间在等待上面。

为了避免这种无谓的等待跟提高用户的操作体验,微软第一个站出来,开发了

Microsoft最初开发的

这里我们简单的介绍一下

旧版本IE下创建

在IE7之前,

function getvar versions = ['MS2];  for (var i = 0; i < versions.length; i++) {    try {      return new ActiveXObject(versions[i]);    } catch (e) {      continue;    }  }};

IE7以及其它现代浏览器下创建

在IE7+以及其它的现代浏览器中,可以简单地使用以下的语句来创建

var xhr = new 

跨浏览器实现

综上所述,我们可以用以下的方法来实现跨浏览器创建

function getif (typeof ) {    return new else {    var versions = ['MS2];    for (var i = 0; i < versions.length; i++) {      try {        return new ActiveXObject(versions[i]);      } catch (e) {        continue;      }    }  }};

 - 创建

 -

 -

 

我们可以通过

当我们发送请求上服务器之后,我们可以通过readyState的属性来监听当前的状态,readyState总过有以下5ge状态:

 - 0 : 还没有进行任何的初始化动作,open method还没有被调用

 - 1 : open method被调用,但是请求还没有send出去

 - 2 : 调用send method发送请求

 - 3 : 数据加载当中

 - 4 : 请求完成

当readyState在不同的状态之间切换的时候,会触发onreadystatechange事件,我们可以通过绑定这个事件,对请求的响应状态进行实时的监控:

window.onload = function () {  var xhr = get= function () {    if (xhr.readyState === 4) {    }  }};

通常我们最为关心就是当readyState为4的情况,此时我们可以通过查看当前的HTTP status code,来判定请求是否成功,以下是我们较为常用的status code

 - 200 <= xhr.status < 300,当satus code在这个区间的时候,表示请求成功

 - 304,这个代码表示not modified since last request, the response will get from browser personal cache,依然表示一个成功的请求

 - 另外有一种情况我们需要留意,当我们请求一个本地文件(protocol为file://)的时候,此时的status code返回的是undefined

 - 另外一个比较特殊的情况是,当Safari浏览器,the response is not modified since last request,这种情况下它返回的并不是304,而是一个undefined

因此我们可以通过以下的代码还检验一个HTTP请求是否成功:

function httpSuccess(xhr) {  return (200 <= xhr.status < 300) || xhr.status === 304 ||       (xhr.location.host.protocol === 'file://' && xhr.status === undefined) ||       (userAgent.indexOf('Safari') !== -1 && xhr.status === undefined);}

我们一般不通过statusText属性来判断当前的请求是否成功,因为不同的浏览器有不同实现,对于相同的结果,可能返回不同的描述。

我们可以通过responseText跟response

window.onload = function () {  var xhr = get= function () {    if (xhr.readyState === 4) {      if (httpSuccess(xhr)) {        console.debug(xhr.responseText);      }    }  }};

序列化请求数据

当我们发送一个请求上服务器的时候,我们通常会向服务器发送额外的请求数据,这个时候我们就需要先将请求数据进行格式化,把它转变成服务器可以处理的形式,通常我们把这个过程称之为序列化。

在客户端,我们通常是以以下的两种形式向服务器提交请求参数:

 - JSON格式 : {'userName' : 'AndyLuo', 'title' : 'Software Engineering'}

 - 表单数据 : [userNameElem, titleElem]

通过序列化我们最终需要把它们转换成诸如 https://www.someurl.com?name1=value1&name2=value2&name3=value3的形式

function serialize(data) {  var rtnValue = '';  if (Object.prototype.toString.call(data) === '[Object Array]') {    // handle form elements case    for (var i = 0; i < data.length; i++) {      var elem = data[i];      rtnValue = addUrlParameter('', elem.name, elem.value);    }  } else {    for (var k in data) {      rtnValue = addUrlParameter('', k, data[k]);    }  }    return rtnValue;}function addUrlParameter(url, name, value) {  if (url.indexOf('?') == -1) {    url += '?';  } else {    url += '&';  }    url += encodeURIComponent(name) + '=' + encodeURIComponent(value);    return url;}

HTTP Header

我们可以通过xhr.setRequestHeader(hdrName, hdrValue)来订制header value,也可以通过xhr.getResponseHeader(hdrName)以及xhr.getAllResponseHeaders()来获取服务器响应的header头部信息。

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

xhr.setRequestHeader('Content-Type', 'application/

xhr.setRequestHeader('userName', 'AndyLuo');

xhr.getResponseHeader('userName');

xhr.getALLResponseHeaders();

另外,xhr还提供了一个非常有用的方法overwriteMimeType,我们可以通过修改MIME类型以获得正确的返回,比如,当前的服务器返回的是一个

GET/ POST 方式请求数据

window.onload = function () {  var xhr = get= function () {    if (xhr.readyState === 4) {      if (httpSuccess(xhr)) {        console.debug(xhr.responseText);      }    }  }    xhr.open('GET', '/someurl/somepage?param1=value1&param2=value2', true);  xhr.send(null);};

window.onload = function () {  var xhr = get= function () {    if (xhr.readyState === 4) {      if (httpSuccess(xhr)) {        console.debug(xhr.responseText);      }    }  }    xhr.open('POST', '/someurl/somepage', true);  xhr.send('param1=value1&param2=value2');};

 

 

随着

FormData对象,再POST方法请求数据的时候不,可以方便的对表单数据进行操作,其具体的用法有以下两种方式:

 - FormData.append(name, value)

 - new FormData(formElement)

var formData = new FormData();formData.append('userName', 'AndyLuo');xhr.send(formData);xhr.send(new Formdata(document.forms[0]));

另一个值得一提的是,Level 2引进了以下的event事件:

 - loadStart : 当客户端接收到第一个字节的时候,触发此事件

 - progress : 当客户端持续接收到一个或者多个数据的时候,触发此事件

 - error : 当处理请求出现错误的时候

 - abort : 当取消当前请求的时候

 - load : 请求完成的时候

 - loadEnd : 请求结束的时候触发此事件

AJAX using

前面我们提到了传统的浏览器服务器数据交互的模式,用户提交一个请求,等待服务器处理,服务器处理完请求返回数据给浏览器,浏览器重新加载页面显示结果。这样的交互模式并非十分友好,有的时候我们仅仅需要服务返回一点点的信息,但是我们还是一样要经历一系列的动作和等待,而且这这个这个过程中,我们除了等待什么事情也做不了,对于当前的操作页面也完全失去了控制。

我们希望有这样一种方式,当我们需要服务器信息的时候,我们点击页面中的某个按钮或者链接,向服务器提出数据请求,然后我们保留在当前页面继续下面的操作,当服务器返回数据的时候,我们可以很方便的把数据更新到当前页面合适的位置,这个时候,AJAX就应运而生了。

AJAX是Asynchronize JavaScript and

由于AJAX的应用非常广泛,为了简化我们代码的开发,我们可以把它开发成为一个通用的module,后续工作中,我们只需要通过这个module就可以很方便的实现AJAX的操作,具体如下所示:

 

function ajax (options) {  options = {    url : options.url || '',    method : options.method || 'POST',    type : options.type || ',    asyn : options.asyn || true,    timeout : options.timeout || '',    onSuccess : options.onSuccess || function () {},    onError : options.onError || function () {},    onComplete : options.onComplete || function () {},    onTimeout : options.onTimeout || function () {},    data : options.data || {}  };    var requestDone = false;    try {    parseInt(timeout);    setTimeout(function() {      requestDone = true;      options.onTimeout();    }, timeout * 1000);  } catch (e) {}    var xhr = createXHR();  xhr.onreadystatechange = function () {    if (xhr.readyState === 4 && !requestDone) {      if (httpSuccess(xhr)) {        options.onSuccess(httpData(xhr, options.type));      } else {        options.onError(httpData(xhr, options.type));      }            options.onComplete();            xhr = null;    }  };    if (options.method.toLowerCase() === 'post') {    xhr.open(options.method, options.url, options.aysn);    xhr.send(serialize(options.data));  } else {    options.url = addURLParameters(options.url, serialize(options.data));    xhr.open(options.method, options.url, options.aysn);    xhr.send(null);  }  };function createXHR() {  if (typeof  undefined) {    return new else {    var versions = ['MS2];        for (var i = 0; i < versions.length; i++) {      try {        return new ActiveXObject(versions[i]);      } catch (e) {        continue;      }    }  }};function httpSuccess (xhr) {  try {    return (200 <= xhr.status < 300)       || (xhr.status === 304)      || (!xhr.status && location.protocol === 'file:')      || (window.userAgent.indexOf('Safari') !== -1 && typeof xhr.status === undefined);  } catch (e) {    return false;  }    return false;};function httpData (xhr, type) {  var contentType = xhr.getResponseHeader('Content-Type');  var is;  var data = (type === ' xhr.responseif (type === 'script') {    eval.call(window, data);  }    return data;};function serialize(data) {  var results = [];  if (Object.prototype.toString.call(data) === '[Object Array]') {    for (var i = 0; i < data.length; i++) {      data.push(encodeURIComponent(data[i].name) + '=' + encodeURIComponent(data[i].value));    }  } else {    for (var key in data) {      data.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));    }  }    return results.join('&');}function addURLParameters(url, paramStr) {  if (url.indexOf('?') === -1) {    url += '?';  } else {    url += '&';  }    return url + paramStr;}

下面是一个简单的使用例子:

 

<!DOCTYPE html><html>  <head>    <title>AJAX DEMO</title>    <script type='text/javascript' src='ajax.js'></script>  </head>  <body>    <div id='weather'>      What's the weather like today?      <input type='button' id='queryBtn' name='queryBtn' value='Query' />    </div>    <div id='console'>      Today's Weather:<span id='result'></span>    </div>    <script type="text/javascript">      window.onload = function () {        var queryBtn = document.getElementById('queryBtn');        queryBtn.addEventListener('click', function() {          ajax({            url : '<replace your domain url here>',            type : 'text',            onSuccess : function (data) {              var result = document.getElementById('result');              result.innerHTML = data;            },            onError : function (data) {              console.debug('fail');            }          });        }, false);      };    </script>  </body></html>

 

运行结果如下所示: