使用 XMLHttpRequest(一):发送请求获取响应


Javascript-Fetch-API.png

XMLHttpRequest

浏览器在 XMLHttpRequest 类上定义了它们的 HTTP API,这个类的每个实例都表示一个独立的请求/响应对,并且这个对象的属性和方法允许指定请求细节和提取响应数据。

注:Microsoft 最早把 XMLHttpRequest 对象引入到 IE5 中,且在 IE5 和 IE6 中它只是一个 ActiveX 对象。

一个 HTTP 请求由四部分组成:

  • HTTP 请求方法或动作(verb)
  • 正在请求的URL
  • 可选的请求头信息(包含身份认证信息)
  • 可选的请求主体

一个 HTTP 响应包含三个部分:

  • 状态码
  • 响应头
  • 响应主体

关于 HTTP 请求和响应的底层细节,可以参考网络协议系列中对应的 HTTP 协议教程:HTTP 协议概述

指定请求

创建 XMLHttpRequest 对象之后,发起 HTTP 请求的下一步是调用 XMLHttpRequest 对象的 open()方法去指定这个请求的两个必需部分:方法和URL。如果请求头的话,可以通过 setRequestHeader 方法进行设置。发起 HTTP 请求的最后一步是指定可选的请求主体并通过 send() 方法发送。

下面是一个通过 POST 方法发送文本字符串到服务器的示例:

function postMessage(msg) {
  var request = new XMLHttpRequest();
  request.open('POST', "/log.php");
  request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
  request.send(msg);
}

取得响应

我们可以通过 XMLHttpRequest 对象的 statusstatusText 属性获取 HTTP 状态码,通过 getResponseHeader()getAllResponseHeaders() 查询响应头,响应主体可以通过responseText 属性获取文本形式,通过 responseXML 获取 Document 形式。

通过 XMLHttpRequest 发送 HTTP 请求是异步非阻塞的,为了在响应准备就绪时得到通知,必须监听 XMLHttpRequestreadystatechange 事件,理解这个事件必须先了解 readyState 属性。

readyState 是一个整数,表示 HTTP 请求的状态:

理论上,每次 readyState 属性改变都会触发 readystatechange 事件,所以我们要监听响应完成状态,只需要在事件处理程序里一直检测 readyState 属性值即可:

function getText(url, callback) {
  var request = new XMLHttpRequest();
  request.open("GET", url);
  request.onreadystatechange = function () {
    if (request.readyState === 4 && request.status === 200) {
      var type = request.getResponseHeader("Content-Type");
      if (type.match(/^text/))
        callback(request.responseText);
    }
  };
  request.send(null);
}

同步响应

XMLHttpRequest 也支持同步响应,如果把 false 作为第三个参数传递给 open() 方法,那么 send() 将阻塞直到请求完成,这种情况下,不需要事件处理程序:

function getText(url, callback) {
  var request = new XMLHttpRequest();
  request.open("GET", url, false);
  request.send(null);

  if (request.status !== 200)
    throw new Error(request.statusText);

  var type = request.getResponseHeader("Content-Type");
  if (!type.match(/^text/))
    throw new Error("Expected textual response; got: " + type);

  callback(request.responseText);
}

响应解码

如果服务器想发送诸如对象或数组这样的结构化数据作为响应,它应该传输 JSON 编码的字符串数据。当接收 JSON 格式数据时,可以将 responseText 传递给 JSON.parse() 进行解析。

服务器响应的正常解码是假设服务器为这个响应发送了「Content-Type」和正确的 MIME 类型,否则将出现与预期不符的结果。当然你也可以在客户端覆盖响应中的 MIME 类型:

request.overrideMimeType("text/plain; charset=UTF-8");

点赞 取消点赞 收藏 取消收藏

<< 上一篇: 文本输入和键盘事件

>> 下一篇: 使用 XMLHttpRequest(二):编码请求主体