[译]深入剖析XMLHttpRequest规范

帅华君翻译的所有英文文档、资料尽可能的保证不出现漏翻和错翻,但还是强烈建议所有人去阅读官方发布的英文一手资料,只有你自己知道你还需要掌握哪些知识点,阅读官方文档才不会遗漏任何知识点。

概要

XMLHttpRequest标准为客户端和服务器端传输数据提供了脚本化的客户端功能API。

目录

  • 1 介绍
    • 1-1 历史之源
  • 2 一致性
    • 2-1 可扩展性
  • 3 术语
  • 4 XMLHttpRequest接口
    • 4-1 构造器
    • 4-2 垃圾回收机制
    • 4-3 事件处理器
    • 4-4 状态码
    • 4-5 请求
      • 4-5-1 open() 方法
      • 4-5-2 setRequestHeader() 方法
      • 4-5-3 timeout 属性
      • 4-5-4 withCredentials 属性
      • 4-5-5 upload() 方法
      • 4-5-6 send() 方法
      • 4-5-7 abort() 方法
    • 4-6 响应
      • 4-6-1 responseURL() 属性
      • 4-6-2 status() 属性
      • 4-6-3 statusText() 属性
      • 4-6-4 getResponseHeader() 方法
      • 4-6-5 getAllResponseHeaders() 方法
      • 4-6-6 响应体
      • 4-6-7 overrideMineType() 方法
      • 4-6-8 responseType 属性
      • 4-6-9 response 属性
      • 4-6-10 responseText 属性
      • 4-6-11 responseXML 属性
    • 4-7 事件概要
  • 5 FormData 接口
  • 6 ProgressEvent 接口
    • 6-1 使用 ProgressEvent接口 触发事件
    • 6-2 建议使用的 ProgressEvent接口 事件名
    • 6-3 安全考虑
    • 6-4 用例
  • 参考
    • 规范参考文献
  • 鸣谢
  • 索引
    • 规范条款
    • 参考条款
  • 接口描述信息

介绍

本章未规范化。

XMLHttpRequest 对象是用来探测远程资源的API。

由于历史遗留原因,XMLHttpRequest 这个名字并不指其只接受并处理XML,而是代表一种异步加载技术。

使用案例

1.获取XML文档数据
function processData(data) {
  // taking care of data
}

function handler() {
  if(this.status == 200 &&
    this.responseXML != null &&
    this.responseXML.getElementById('test').textContent) {
    // success!
    processData(this.responseXML.getElementById('test').textContent);
  } else {
    // something went wrong
    …
  }
}

var client = new XMLHttpRequest();
client.onload = handler;
client.open("GET", "unicorn.xml");
client.send();
2.如果你只是想向服务器端发送信息
function log(message) {
  var client = new XMLHttpRequest();
  client.open("POST", "/log");
  client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
  client.send(message);
}
3.或者你想获取文档在服务器端的状态信息
function fetchStatus(address) {
  var client = new XMLHttpRequest();
  client.onload = function() {
    // in case of network errors this might not give reliable results
    returnStatus(this.status);
  }
  client.open("HEAD", address);
  client.send();
}

1-1 历史之源

XMLHttpRequest对象是WHATWG组织在HTML标准化之路上推出的接口之一(基于多年前微软在这方面的部分已实现的功能与机制)。在2006年,该规范移交至W3C,一些扩展功能与机制(请求进度事件 和 跨域请求)是直到2011年的另一个草案时才被提出,不过最终这两个草案合并了,这是因为从高瞻远瞩的角度来看,两个分开的草案本是一个整体。最后于2012年该草案又回到了WHATWG。

人们可以从以下的邮件列表档案中寻找当时讨论该草案的过程:

2 一致性

该规范的所有的图表,用例和笔记都为标准化,在每一章中也都会明确指出为标准化,凡是未明确指出的都为标准化的,人们可以放心使用。

“MUST”“MUST NOT”“REQUIRED”“SHOULD”“SHOULD NOT”“RECOMMENDED”“MAY”“OPTIONAL” ,在该规范中被明确标准化的部分出现的这些关键字将会按照 RFC2119 标准描述。为了可读性考虑,在该规范中出现的这些单词并不会总是大写字符。[RFC2119]

2-1 可扩展性

我们强烈鼓励用户代理(浏览器厂商,设备厂商)、工作组和其他有兴趣的团体与WHATWG社区一起讨论新的功能。

3 术语

该规范的DOM,DOM解析和序列化,编码,远程获取,文件API,HTML,URL,Web IDL和XML中使用的术语,全部超链接:

[DOM]
[DOM]
[ENCODING]
[FETCH]
[FILEAPI]
[HTML]
[HTTP]
[URL]
[WEBIDL]
[XML]
[XMLNS]

使用HTML的常用排版方式 [HTML]

规范中的**user credentials*术语,指的是cookie,HTTP证书和TLS客户端证书,特别要指出的是,它并不代表代理证书或者 Origin 头信息。

4 XHR 接口

接口描述信息

[Exposed=(Window,DedicatedWorker,SharedWorker)]
interface XMLHttpRequestEventTarget : EventTarget {
  // event handlers
  attribute EventHandler onloadstart;
  attribute EventHandler onprogress;
  attribute EventHandler onabort;
  attribute EventHandler onerror;
  attribute EventHandler onload;
  attribute EventHandler ontimeout;
  attribute EventHandler onloadend;
};

[Exposed=(Window,DedicatedWorker,SharedWorker)]
interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
};

enum XMLHttpRequestResponseType {
  "",
  "arraybuffer",
  "blob",
  "document",
  "json",
  "text"
};

[Constructor,
 Exposed=(Window,DedicatedWorker,SharedWorker)]
interface XMLHttpRequest : XMLHttpRequestEventTarget {
  // event handler
  attribute EventHandler onreadystatechange;

  // states
  const unsigned short UNSENT = 0;
  const unsigned short OPENED = 1;
  const unsigned short HEADERS_RECEIVED = 2;
  const unsigned short LOADING = 3;
  const unsigned short DONE = 4;
  readonly attribute unsigned short readyState;

  // request
  void open(ByteString method, USVString url);
  void open(ByteString method, USVString url, boolean async, optional USVString? username = null, optional USVString? password = null);
  void setRequestHeader(ByteString name, ByteString value);
           attribute unsigned long timeout;
           attribute boolean withCredentials;
  [SameObject] readonly attribute XMLHttpRequestUpload upload;
  void send(optional (Document or BodyInit)? body = null);
  void abort();

  // response
  readonly attribute USVString responseURL;
  readonly attribute unsigned short status;
  readonly attribute ByteString statusText;
  ByteString? getResponseHeader(ByteString name);
  ByteString getAllResponseHeaders();
  void overrideMimeType(DOMString mime);
           attribute XMLHttpRequestResponseType responseType;
  readonly attribute any response;
  readonly attribute USVString responseText;
  [Exposed=Window] readonly attribute Document? responseXML;
};

每一个 XMLHttpRequest 对象都有一个相关联的 XMLHttpRequestUpload 对象。

每一个 XMLHttpRequest 对象都有一个相关联的 state, 该状态信息有 unsentopenedheaders receivedloadingdone 这几种值。

每一个 XMLHttpRequest 对象都有一个相关联的 send() 标志,除非特别标明否则它是 unset

4-1 构造器

client = new XMLHttpRequest()
// 返回一个新的 XMLHttpRequest 对象。

XMLHttpRequest() 构造器,当调用时,必须返回一个新的 XMLHttpRequest 对象。

4-2 垃圾回收机制

每一个 XMLHttpRequest 对象在一下情况下绝对不能自动回收内容:1、调用 send() 方法后 stateopened 状态。2、已经接收了响应头。 3、正在加载 loading。4、有至少一个如下类型的事件监听器被开发者注册(readystatechangeprogressaborterrorloadtimeoutloaded)。

如果 XMLHttpRequest 对象被作为垃圾回收(内存),而此时请求链接已经建立,用户代理必须通过 XMLHttpRequest 对象立即终止正在进行的请求远程资源的操作。

4-3 事件处理器

如下的事件处理器(和他们对应的处理的事件类型),必须作为 XMLHttpRequestEventTarget 的继承属性被支持。

event handler event handler event type
onloadstart loadstart
onprogress progress
onabort abort
onerror error
onload load
ontimeout timeout
onloadend loadend

如下的事件处理器(和他相应的事件类型),必须被支持,并且完全作为 XMLHttpRequest 对象的属性。

event handler event handler event type
onreadystatechange readystatechange

4-4 状态码

client.readyState
// 返回客户端的状态

readyState 属性的存取器必须返回下方表格第二列的值,表格中的每一行的第一列是 context objectstate

unsent UNSENT (numeric value 0) The object has been constructed.
opened OPENED (numeric value 1) The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the fetch can be initiated using the send() method.
headers received HEADERS_RECEIVED (numeric value 2) All redirects (if any) have been followed and all HTTP headers of the response have been received.
loading LOADING (numeric value 3) The response’s body is being received.
done DONE (numeric value 4) The data transfer has been completed or something went wrong during the transfer (e.g. infinite redirects).

4-5 请求

每一个 XMLHttpRequest 对象都有如下的相关联的概念:请求方法请求地址自定义的请求头请求体是否开启同步的标志上传完成标志上传监听器标志超时标志

自定义请求头的初始状态的是空的header list

请求体 初始状态为 null。

同步标志上传完成标志上传监听器标志超时标志的初始化状态为 unset。

XMLHttpRequest 上注册一个或更多个事件监听器会将结果 CORS-preflight request。(那是因为注册一个事件监听器导致 上传监听器 被设置,这将导致 ** 被设置。)

4-5-1 open() 方法
client . open(method, url [, async = true [, username = null [, password = null]]])

设置 request methodrequest URLsynchronous flag

如果方法不是一个可用的HTTP方法,或者 ur 不能被接续,则l抛出一个 语法错误(SyntaxError)。

如果方法因为不敏感的大小写(‘CONNECT’,‘TRACE’,‘TRACK’),则抛出一个安全错误(SecurityError)。

如果没有采用异步请求的方式,当前的全局对象是一个Window对象,并且超时(timeout)属性不为0或者responseType属性不为空的字符串,则抛出不可用的权限错误(InvalidAccessError)。

同步的 XMLHttpRequest请求已经渐渐的被网络平台开发者所淘汰,因为这严重影响到用户体验。如果当前全局对象为Window,请开发者切勿将是否开启异步加载设为 false。我们强烈建议用户代理借助浏览器的开发者工具可以通过抛出 InvalidAccessError 的错误警告开发者们不要这样做。

open(method, url)open(method, url, async, username, password) 方法,当被调用时,必须执行如下步骤:

  • 1、如果上下文对象的相关设置对象有一个可用的文档,并且没有被完全激活,抛出 InvalidStateError 错误。
  • 2、如果方法不可用,抛出 SyntaxError 错误。
  • 3、如果方法是被禁用的,抛出 SecurityError 错误。
  • 4、序列化方法。
  • 5、使用上下文中的API base URL 解析传入的 url,并赋值给 parsedURL。
  • 6、如果 parsedURL 解析失败,抛出 SyntaxError 错误。
  • 7、如果开发者省略了 async(是否异步加载) 参数。默认设置为 true(开启异步加载),并且设置 username 和 password 为 null。

遗憾的是,默认的 aysnc 参数并不为 undefined

  • 8、如果 parsedURL 的主机地址不为空,执行以下步骤:
    • 如果 username 参数不为空,将 parsedURL 加入 username 。
    • 如果 password 参数不为空,将 parsedURL 加入password。
  • 9、如果一部标志已开启,且当前的全局对象为 Window,并且超时属性不为0 或者 responseType 属性不为空字符串,那么抛出 InvalidAccessError 错误。
  • 10、使用如下的对象设置可变量:
    • 重置 send() 标志 和 *upload listener * 标志。
    • 为方法设置请求方法。
    • 设置请求地址为 parsedURL。
    • 如果异步标志为 false,设置同步标志,否则重置同步标志。
    • 清空用户自定义的请求头。
    • 设置接受字节为空的字节序列。
    • 设置响应对象为 null。
  • 12、如果 state 为开放,执行以下子步骤:
    • 设置 state 为 opened。
    • 触发 readystatechange 事件。

之所有 open() 方法有两个构造器,是因为过去的编辑器的限制。

4-5-2 setRequestHeader() 方法
client . setRequestHeader(name, value)

将用户自定义的请求头们合并到待发送的请求头。

如果当前状态为 not opened 或者 send() 标志被设置(也就是无法再设置请求头了),则抛出 InvalidStateError(不可用的状态错误) 异常。

如果 name 参数不是头信息的合法属性或者 value 也不是请求头的合法值,则抛出 SyntaxError(语法错误) 异常。

正如下方算法指出的,某些请求头不会被设置。如果他们在 send() 方法调用前没有被开发者明确的设置,则其他的一些确定的请求头用户代理将由用户代理掌控。

setRequestHeader(name, value) 方法必须执行如下步骤:

  • 1、如果 state 未打开,抛出 InvalidStateError(不可用的状态错误) 异常。
  • 2、如果 send() 标志已经被设置,抛出 InvalidStateError(不可用的状态错误)异常。
  • 3、序列化值。
  • 4、如果 name 参数不正确,则抛出 SyntaxError(语法错误) 异常。

空的字节序列代表空的请求值。

  • 5、如果 name 参数是一个被禁止的请求头名称则终止这些步骤。
  • 6、联合用户自定义的请求头信息 name/value 。

用例

该用户演示了如果对同意请求头的属性设置了两次会发生什么:

// The following script:
var client = new XMLHttpRequest();
client.open('GET', 'demo.cgi');
client.setRequestHeader('X-Test', 'one');
client.setRequestHeader('X-Test', 'two');
client.send();

// …results in the following header being sent:
// X-Test: one, two
4-5-3 timeout 属性
client . timeout

超时时间将会以毫秒作为单位,当开发者设置了一个非零的值时,如果经过了超时的时长仍未完成并返回响应信息,将导致获取远程资源的失败。并且同步的标志为被设置,一个 timeout 的事件将会被派发到事件监听函数上,否则针对 send() 的TimeoutError 异常将会被抛出 。

当设置:如果同步的标志被设置并且当前的全局对象为Window对象,则抛出 InvalidAccessError(不可用的权限错误) 异常 。

timeout 超时属性必须返回它本身的值,初始化的超时时长必须为0。

设置 timeout 属性必须执行以下步骤:

  • 1、如果当前全局对象是 Window 对象,并且同步标志被设置,则抛出 InvalidAccessError(不可用的权限错误) 异常。
  • 2、设置它自身的值为新的值。

这意味着,即使正在获取远程资源,也可以随时设置 timeout 属性,如果你这样做了,接口将会计算自开始请求获取远程响应已过去的时间。

4-5-4 withCredentials 属性
client . withCredentials

user credentials被包含在一个跨域的请求重视为 True。当为被排除在一个跨域的请求并且相应信息忽略了cookie是为 False。初始化为 false。当设置:如果 *state* 不是 *unsent* 或者是 *opened* 状态,或者已经设置了 *send()* 标志,抛出 InvalidStateError (不可用的状态错误)异常

withCredentials 属性必须返回它自身的值,初始化值必须为 false

设置 withCredentials 属性必须执行以下步骤:

  • 1、如果 state 标志为 not unsent 或者 opened,抛出 InvalidStateError(不可用的状态错误) 异常。
  • 2、如果 send() 标记已经被设置。抛出 InvalidStateError(不可用的状态错误) 异常,
  • 3、设置withCredentials 属性值为给定的值。

当获取 *same-origin* 资源,withCredentials 属性没有任何作用

4-5-5 upload() 方法
client . upload

返回相关联的 XMLHttpRequest 对象 ,其可被用来收集当数据正在向服务器传输时的传输信息。

upload 属性必须返回相关联的 XMLHttpRequest 对象。

早期的规范说明中,每一个 *XMLHttpRequest* 对象都有一个相关联的 *XMLHttpRequestUpload* 对象。

4-5-6 send() 方法
client . send([body = null])

初始化这一请求,该方法的参数项可选的提供请求体,如果开发者使用 *GET* 或者 *HEAD* 请求方法,则该请求体将会被忽略。如果 *not opened* 或者 *send()* 标志已被设置,则抛出 *InvalidStateError*(不可用的状态错误) 异常。

send(body) 方法必须执行以下这些步骤:

  • 1、如果 statenot opened,抛出 InvalidStateError(不可用的状态错误) 异常。
  • 2、如果已经设置了 send() 标志,则抛出 InvalidStateError(不可用的状态错误) 异常。
  • 3、如果请求方法为 GET 或者 HEAD ,则将 body 替换为 null
  • 4、如果 bodynull ,执行以下步骤
    • 否则,让 encodingmimeTypenull ,并且执行以下规则,并将其转换至 body 中。
      Document
      设置 encodingUTF-8
      如果 body 是 HTML document,设置 mimeTypetext/html,否则重写 application/xml,之后将 ;charset=UTF-8 添加到 mimeType 中。
      设置 body 的请求体,序列化,转换为 Unicode 并使用 utf-8 解码。
      BodyInit
      如果 body 为字符串,设置 encodingUTF-8
      设置 请求体 和 mimeType 到 extracting body 中。
      如果 mimeTypenon-null 并且 用户自定义的请求头不包含 Content-Type ,那么将 Content-Type 和 mimeType 添加到用户请求头中。
      否则,如果请求头中 byte-case-insensitive 匹配到了 Content-Type 为可用的 mimeType,其有 charset 参数,并且不是 byte-case-insensitive ,然后 encodingnot null,然后设置所有的 charset 参数(值不为 byte-case-insensitive)。
  • 5、如果一个或更多个事件监听器被注册到相关的 XMLHttpRequestUpload 对象,那么设置 upload listener flag
  • 6、初始化 req 为一个新的 request,使用如下步骤初始化:
  • 7、重置 upload complete flag.
  • 8、重置 timed out flag.
  • 9、如果请求body为空,设置 upload complete flag
  • 10、设置 send() 标志。
  • 11、如果 synchronous flag被重置,执行如下子步骤:
4-5-7 abort() 方法
client . abort()

取消一切网络相关的请求活动。

readystatechange事件将不会被派发。

4-6 响应

每一个 XMLHttpRequest 都有相关联的响应。除非出现 network error

XMLHttpRequest 也拥有相关联的接收字节(字节序列)。除非为空的字节序列。

4-6-1 responseURL()

如果responseurl 为空,并且使用使用 exclude fragment 标志,responseURL 属性必须返回空的字符串 。

4-6-2 status()

status 属性必须返回 response状态

4-6-3 statusText()

statusText 属性必须返回 response状态信息

4-6-4 getResponseHeader()

getResponseHeader(name) 方法必须执行以下步骤:

The Fetch Standard filters response’s header list. [FETCH]

var client = new XMLHttpRequest();
client.open("GET", "unicorns-are-teh-awesome.txt", true);
client.send();
client.onreadystatechange = function() {
  if(this.readyState == this.HEADERS_RECEIVED) {
    print(client.getResponseHeader("Content-Type"));
  }
}

print 函数将处理一些事情

text/plain; charset=UTF-8

4-6-5 getAllResponseHeaders()

当调用 getAllResponseHeaders() 方法时,必须执行如下步骤:

  • 1、初始化 output 为空的字节序列。
  • 2、初始化 headers ,将 responseheader list 执行 sort and combine 处理,处理结果赋值给 headers
  • 3、对于 headers 中每一个 header 的名值对,使用 0x3A 0x20 加以修饰。
  • 4、返回 output

The Fetch Standard filters response’s header list. [FETCH]

用例

var client = new XMLHttpRequest();
client.open("GET", "narwhals-too.txt", true);
client.send();
client.onreadystatechange = function() {
  if(this.readyState == this.HEADERS_RECEIVED) {
    print(this.getAllResponseHeaders());
  }
}

print 函数的执行结果如下:

connection: Keep-Alive
content-type: text/plain; charset=utf-8
date: Sun, 24 Oct 2004 04:58:38 GMT
keep-alive: timeout=15, max=99
server: Apache/1.3.31 (Unix)
transfer-encoding: chunked
4-6-6 响应体

response MIME type 是执行以下步骤的产出结果:

  • 1、初始化 mimeType
  • 2、如果 mimeType 为空的字节序列,那么设置 mimeTypetext/xml
  • 3、返回 mimeType

override MIME type 初始值为 null,并且可以通过调用 overrideMimeType() 函数得到。Final MIME typeoverride MIME type 除非其为 null。

response charsetContent-Type 中的 charset 参数的值,或者如果没有 charset 参数或header不能被解析或者被忽略则为 null ,override charset 初始化为 null,并且可以通过调用 overrideMimeType() 方法得到。Final charset 即是 override charset 除非 其为 null。

XMLHttpRequest 对象拥有一个相关联的 response object (an object, filure, or null)。除非设置了状态否则为 null。

4-6-7 overrideMineType()
client . overrideMimeType(mime)

这样设置让响应头的 Content-Type 就好像是 mime

如果 stateloading 或者 done 抛出 InvalidStateError(不可用的状态错误) 异常。

overrideMimeType(mime) 方法必须执行如下步骤:

  • 1、如果 stateloading 或者 done ,抛出 InvalidStateError(不可用的状态错误) 异常。
  • 2、设置 override MIME typeapplication/octet-stream
  • 3、如果 mime 是可解析的 MIME type, 那么设置 override MIME type 为他自己的 MIME type portion
  • 4、如果 override MIME type 拥有 charset 参数,那么设置 ovveride charset 为其值。
4-6-8 responseType
client . responseType [ = value ]

返回响应的数据类型。

可以赋值,改变响应类型,默认的为空字符串,arraybufferblobdocumentjsontext

当设置:如果 current global object 不是 Window 对象则设置 document 会被忽略。

当设置:如果 stateloading 或者 done 则抛出 InvalidStateError(不可用的状态错误) 异常。

当设置:如果 syncchronous flag 被设置并且当前的全局对象是 Window 对象则抛出 InvalidAccessError(不可用的权限错误) 异常。

responseType 属性必须返回他自身的值,初始化的值必须为空的字符串。

4-6-9 response
client . response

返回响应体。

4-6-10 responseText
client . responseText

返回文本响应。

如果 responseType 不为空字符串或者 text 则抛出 InvalidStateError(不可用的状态错误) 异常。

4-6-11 responseXML
client . responseXML

返回 document response

如果 responseType 不为空的字符串或者 document 抛出 InvalidStateError(不可用的状态错误) 异常。

4-7 事件概要

本章节内容未标准化。

下方的事件由 XMLHttpRequestXMLHttpRequestUpload 对象派发:

Event name Interface Dispatched when…
readystatechange Event The readyState attribute changes value, except when it changes to UNSENT.
loadstart ProgressEvent The fetch initiates.
progress ProgressEvent Transmitting data.
abort ProgressEvent When the fetch has been aborted. For instance, by invoking the abort() method.
error ProgressEvent The fetch failed.
load ProgressEvent The fetch succeeded.
timeout ProgressEvent The author specified timeout has passed before the fetch completed.
loadend ProgressEvent The fetch completed (success or failure).

5 FormData 接口

typedef (File or USVString) FormDataEntryValue;

[Constructor(optional HTMLFormElement form),
 Exposed=(Window,Worker)]
interface FormData {
  void append(USVString name, USVString value);
  void append(USVString name, Blob blobValue, optional USVString filename);
  void delete(USVString name);
  FormDataEntryValue? get(USVString name);
  sequence<FormDataEntryValue> getAll(USVString name);
  boolean has(USVString name);
  void set(USVString name, USVString value);
  void set(USVString name, Blob blobValue, optional USVString filename);
  iterable<USVString, FormDataEntryValue>;
};

FormData 对象表示 entries 的有序列表。每一个 enry 都由 namevalue 组成。

为了与其他算法进行交互,entry 的类型为 string,如果他的 value 是字符串或者 file,如果 entry的类型为 file ,并且 value 不是 File 对象,则 filename 为空的字符串,否则他的 filename 即为 entry’s name 属性。

FormData 含有的方法有:

  • append(name, value)
  • append(name, value, filename)
  • delete(name)
  • get(name)
  • getAll(name)
  • has(name)
  • set(name, value)
  • set(name, value, filename)

6 ProgressEvent

[Constructor(DOMString type, optional ProgressEventInit eventInitDict),
 Exposed=(Window,DedicatedWorker,SharedWorker)]
interface ProgressEvent : Event {
  readonly attribute boolean lengthComputable;
  readonly attribute unsigned long long loaded;
  readonly attribute unsigned long long total;
};

dictionary ProgressEventInit : EventInit {
  boolean lengthComputable = false;
  unsigned long long loaded = 0;
  unsigned long long total = 0;
};

Events 使用 ProgressEvent 接口。

lengthComputableloadedtotal 属性必须返回当时初始化的值。

6-1 使用 ProgressEvent接口触发事件

触发进度事件。

6-2 建议使用的 ProgressEvent接口事件名

本章节未标准化。

推荐的 events使用的 type 属性值在下方表格中列举出来:

type attribute value Description Times When
loadstart Progress has begun. Once. First.
progress In progress. Once or more. After loadstart has been dispatched.
error Progression failed. Zero or once (mutually exclusive). After the last progress has been dispatched.
abort Progression is terminated.
timeout Progression is terminated due to preset time expiring.
load Progression is successful.
loadend Progress has stopped. Once. After one of error, abort, timeout or load has been dispatched.

6-3 安全考虑

对于跨域请求,一些处理办法,CORS protocol定义了获取资源的标准。

6-4 用例

在下方 XMLHttpRequest 的例子中。通过进度条展示了获取远程资源的进度:

<!DOCTYPE html>
<title>Waiting for Magical Unicorns</title>
<progress id=p></progress>
<script>
  var progressBar = document.getElementById("p"),
      client = new XMLHttpRequest()
  client.open("GET", "magical-unicorns")
  client.onprogress = function(pe) {
    if(pe.lengthComputable) {
      progressBar.max = pe.total
      progressBar.value = pe.loaded
    }
  }
  client.onloadend = function(pe) {
    progressBar.value = pe.loaded
  }
  client.send()
</script>

版权声明 » 自由转载-署名-非商用-相同方式共享

作者署名 » 陈帅华-探索技术艺术与国学之美

发布日期 » 2017年9月22日 星期五

我要留言