1. XMLHttpRequest

  • readyState: 表示请求状态的整数,取值:
    • UNSENT(0): 对象已创建
    • OPENED(1): open()成功调用,在这个状态下,可以为 xhr 设置请求头,或者使用 send()发送请求
    • HEADERS_RECEIVED(2): 所有重定向已经自动完成访问,并且最终响应的 HTTP 头已经收到
    • LOADING(3): 响应体正在接收
    • DONE(4): 数据传输完成或者传输产生错误
  • onreadystatechange: readyState 改变时调用的函数
  • status: 服务器返回的 HTTP 状态码(如,200, 404)
  • statusText: 服务器返回的 HTTP 状态信息(如,OK,No Content)
  • responseText: 作为字符串形式的来自服务器的完整响应
  • responseXML: Document 对象,表示服务器的响应解析成的 XML 文档
  • abort(): 取消异步 HTTP 请求
  • getAllResponseHeaders(): 返回一个字符串,包含响应中服务器发送的全部 HTTP 报头。每个报头都是一个用冒号分隔开的名/值对,并且使用一个回车/换行来分隔报头行
  • getResponseHeader(headerName): 返回 headName 对应的报头值
  • open(method, url, asynchronous [, user, password]): 初始化准备发送到服务器上的请求。method 是 HTTP 方法,不区分大小写;url 是请求发送的相对或绝对 URL;asynchronous 表示请求是否异步;user 和 password 提供身份验证
  • setRequestHeader(name, value): 设置 HTTP 报头
  • send(body): 对服务器请求进行初始化。参数 body 包含请求的主体部分,对于 POST 请求为键值对字符串;对于 GET 请求,为 null

XMLHttpRequest 是用于 HTTP 协议的,因此 FTP 或 file: 协议不能使用 XMLHttpRequest

setRequestHeader 有一些请求头是你不能指定的。XMLHttpRequest 会帮你设定。不能通过 setRequestHeader() 指定的头有:

Accept-Charset
Accept-Encoding
Connection
Content-Length
Cookie
Cookie2
Content-Transfer-Encoding
TE
Date
Trailer
Expect
Transfer-Encoding
Host
Upgrade
Keep-Alive
User-Agent
Referer
Via
function postMessage(msg) {
  var request = new XMLHttpRequest(); // New request
  request.open('POST', '/log.php');
  request.setRequestHeader('Content-Type', 'text/plain;charset=UTF-8'); // 必须在 `open()` 后、 `send()` 之前调用
  request.send(msg);
  // The request is done. We ignore any response or any error.
}

1.1. 接收响应

通过 XMLHttpRequest 对象的属性或方法获取响应的信息:

  • statusstatusText 分别以数字和文本形式返回 HTTP 状态,如 200“OK”
  • 响应头可以通过 getResponseHeader()getAllResponseHeaders() 获取。 XMLHttpRequest 会自动处理 cookies,因此当你传 “Set-Cookie” 或 “Set-Cookie2” 给 getResponseHeader() 得到的是 null。
  • responseText 是响应的字符串形式,responseXML 是文档形式。

XMLHttpRequest 一般是异步的。send() 方法调用后立即返回。表示响应的属性和方法要等到收到响应后才有效。要判断响应是否就绪,需要监听 readystatechange 事件(或 XHR2 progress 事件)。

readyState 属性是一个整数,表示 HTTP 请求的状态。规范定义了一些常量,但老的浏览器,包括 IE8 未定义,因此很多时候直接使用数字。

  • UNSENT0:open() 尚未被调用
  • OPENED1:open() 已经被调用
  • HEADERS_RECEIVED2:头部已经收到
  • LOADING3:响应正文正在被接收
  • DONE4:响应完成

理论上,每当 readyState 属性改变都会触发 readystatechange 事件。实际中,readyState 变到 0 或 1 可能不触发。send() 调用后一般会触发一次,即使 readyState 仍为 OPENED。一些浏览器在 LOADING 状态会触发多个事件,算进度反馈。所有浏览器当状态变为 4 时都会触发 readystatechange

监听 readystatechange 事件的方法是设置 XMLHttpRequest 对象的 onreadystatechange 属性。也可以用 addEventListener()

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); // Send the request now
}

1.2. 解码响应

响应若是文本,可以通过 responseText 属性获取。

如果服务器发送的是 XML 或 XHTML 文档,你可以通过 responseXML 属性获取解析后的版本。该属性的值是一个 Document 对象。

服务器还可以响应结构化的数据,如 JSON 编码的字符串。只能用 JSON.parse() 解析 responseText 了。

服务器可能响应二进制数据(如图片)。responseText 属性只用于文本,不能用于处理二进制响应。XHR2 定义了一种处理二进制响应的方法,但目前尚没有浏览器支持。

如果服务器响应未设置正确的 MIME 类型,XMLHttpRequest 对象不会解析并设置 responseXML 属性。如果服务器错误的设置了 content-type 的 charset 参数, XMLHttpRequest 解码会出错。为此,XHR2 定义了一个 overrideMimeType() 方法,你如果你知道响应的 MIME,在调用 send() 前调用 overrideMimeType(),让 XMLHttpRequest 忽略响应的 content-type 头。

// Don't process the response as an XML document
request.overrideMimeType('text/plain; charset=utf-8');

1.3. 对请求正文进行编码

1.3.1. Form-encoded 请求

编码表单数据的方法是:对每个表单项的键与值分别进行正常的 URI 编码(特殊字符由十六进制字符替代),用等号分割键值、用 & 分割表单项:

find=pizza&zipcode=02134&radius=1km

这种格式的数据的 MIME 为:application/x-www-form-urlencoded。当你发送这类数据时,必须将请求头 Content-Type 设为该值。

把一个对象按表单编码:

function encodeFormData(data) {
  if (!data) return '';
  var pairs = [];
  for (var name in data) {
    if (!data.hasOwnProperty(name)) continue;
    if (typeof data[name] === 'function') continue;
    var value = data[name].toString();
    name = encodeURIComponent(name.replace(' ', '+'));
    value = encodeURIComponent(value.replace(' ', '+'));
    pairs.push(name + '=' + value);
  }
  return pairs.join('&');
}

表单编码的数据还可以用于 GET 请求,附加到 GET 请求的查询串上:

request.open('GET', url + '?' + encodeFormData(data));

1.3.2. JSON 编码的请求

request.send(JSON.stringify(data));

1.3.3. 上传文件

HTTP 表单总是能发送文件。但直到最近,XHR2 API 才允许通过传 File 对象到 send() 方法上传文件。

获得 File 对象的方法。<input type="file"> 元素有一个 files 属性,是一个类数组的对象,含有 File 对象。拖放 API 通过 dataTransfer.files 属性提供类似结构。

File 类型是 Blob 的子类型。XHR2 实际允许通过 send() 方法发送任何 Blob 对象。若你不显式设置,Blobtype 属性会被用于设置 Content-Type。如果你要上传二进制数据,可以将其转换为 Blob 后上传。

1.3.4. multipart/form-data 请求

若表单既有文件又有其他元素,浏览器无法使用普通的表单编码,要使用一种特殊的 Content-Type: multipart/form-data。这种编码使用一个较长的边界字符串将请求分割成多个部分。

XHR2 定义了一个新的 FormData API,使得发送 multipart 请求变得简单。首先通过 FormData() 构造器创建 FormData 对象。然后通过 append() 方法添加一个个 “parts”,可以是字符串、FileBlob 对象。最后将 FormData 对象传入 send() 方法。

1.4. HTTP 进度事件

XHR2 草案定义了一个新的事件模型。多数现代浏览器支持。使用新的事件模型后就不必再使用 readyState 属性判断请求状态了。

触发顺序如下。当 send() 被调用,触发 loadstart 事件。在服务器响应下载的过程中 而不是上传过程中!!XMLHttpRequest 触发多个 progress 事件,一般每 50 毫秒一次。请求完成后,触发 load 事件。

完成的请求不一定成功。load 事件的处理器需要检查返回的状态码。有三种可能的错误。若请求超时,触发 timeout 事件。若请求被放弃,触发 abort 事件。其他错误,如“太多重定向),触发 error 事件。

对于一个请求,loadaborttimeouterror 这四个事件,浏览器只会触发其中一个。XHR2 草案规定上述四个事件触发后,要再触发一个 loadend 事件。

可以通过 XMLHttpRequestaddEventListener() 方法注册这些事件的处理器。若只需要一个处理器,可以设置相应的处理器属性,如 onprogressonload 等。

进度事件的事件对象,除了一般 Event 对象的属性,如 typetimestamp

  • loaded 属性是已传输的字节数。
  • total 属性是要传输的总的字节数,来自 Content-Length 头。若响应没有该头,该值为 0。lengthComputable 属性,布尔,用于判断到底知不知道响应的长度。

上述是下载的传输,而不是指上传的传输 这几个属性对于计算已加载的百分比:

request.onprogress = function(e) {
  if (e.lengthComputable) progress.innerHTML = Math.round(100 * e.loaded / e.total) + '% Complete';
};

1.5. 上传进度事件

XHR2 允许监控上传 HTTP 请求的进度。XMLHttpRequestupload 属性是一个对象,有自己的 addEventListener() 方法,以及进度事件属性,如 onprogressonload

例如,对于一个 XMLHttpRequest 对象 x,设置 x.onprogress 属性监听响应的下载进度。设置 x.upload.onprogress 监听请求的上传进度。

1.6. 放弃请求与超时

调用 XMLHttpRequest 对象的 abort() 方法可以取消正在进行的请求。并且在 XHR2 中调用 abort() 方法会触发 abort 事件。

XHR2 定义了一个 timeout 属性,指定超时(毫秒)后自动放弃请求,并触发 timeout 事件。目前还没有浏览器支持这一点。但我们可以通过 setTimeout()abort() 自己模拟。

Copyright © Guanghui Wang all right reserved,powered by GitbookFile Modified: 2019-08-25 13:56:34

results matching ""

    No results matching ""