请求种类
通过XMLHttpRequest的请求可以通过同步和异步的方式获取数据,请求的种类在XMLHttpRequest的open()方法的第三三个可选参数async设置。如果这个参数是true或者没有特别指定,那么XMLHttpRequest讲师异步,否则将是同步传输。总而言之,你要尽可能的少使用同步传输。
Note: 在Geoko30.0(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)以后,考虑到用户体验的不好影响,主线程上的异步传输被弃用
处理response
responseXML
属性
如果你使用XMLHttpRequest来获取远程的XML文档的内容,那么responseXML属性将返回一个DOM对象,此对象包含了一个被解析的XML文档,这个文档难解析和计算。下面5大主要的方法来处理这个XML文档:
- 使用 XPath 来强调(指向)部分内容。
- 使用 JXON 将其转化成Javascript对象树
- 手动的解析或者序列化XML成为字符串亦或对象。
- 使用 XMLSerializer 来序列化DOM树变成strings亦或files
- RegExp可以被使用如果你提前知道了XML文档的内容。 如果你想去掉换行符,你可以使用正则来扫描换行符,但是这是不得已才能使用的方法,因为XML文档中的细微改变将会导致该方法的失败。
responseText
属性包括了 HTML 文档
如果你使用XMLHttpRequest来获取远程HTML文件的内容,那么responseText属性是一个包含了一系列HTML标签的字符,难解析和计算。
下面三个方法可以用来处理:
- 使用XMLHttpRequest.responseXML属性
- 使用fragment.body.innerHTML将内容注入到一个document fragment的主体中
- RegExp可以被使用如果你提前知道了HTML的responseText的内容。 如果你想去掉换行符,你可以使用正则来扫描换行符,但是这是不得已才能使用的方法,因为XML文档中的细微改变将会导致该方法的失败。
处理二进制数据
虽然XMLHttpRequest被常用来发送和接受文本化的数据,但是它同样可以发送和接受二进制数据。
var oReq = new XMLHttpRequest(); oReq.open("GET", url); // retrieve data unprocessed as a binary string oReq.overrideMimeType("text/plain; charset=x-user-defined"); /* ... */
XMLHttpRequest Level 2 增加了新的responseType属性将使得二进制数据处理更加简便
var oReq = new XMLHttpRequest(); oReq.onload = function(e) { var arraybuffer = oReq.response; // not responseText /* ... */ } oReq.open("GET", url); oReq.responseType = "arraybuffer"; oReq.send();
监视进程
XMLHttpRequest
提供了监听一系列在请求正在进行中时发生的事件。这些事件包括了定期进度提醒,错误提醒等。
var oReq = new XMLHttpRequest(); oReq.addEventListener("progress", updateProgress); oReq.addEventListener("load", transferComplete); oReq.addEventListener("error", transferFailed); oReq.addEventListener("abort", transferCanceled); oReq.open(); // ... // progress on transfers from the server to the client (downloads) function updateProgress (oEvent) { if (oEvent.lengthComputable) { var percentComplete = oEvent.loaded / oEvent.total; // ... } else { // Unable to compute progress information since the total size is unknown } } function transferComplete(evt) { console.log("The transfer is complete."); } function transferFailed(evt) { console.log("An error occurred while transferring the file."); } function transferCanceled(evt) { console.log("The transfer has been canceled by the user."); }
第3到6行监听,在使用XMLHttpRequest进行数据转换时发送的事件。
Note: 你需要在调用call()事件之前添加监听。否则,监听事件将不会执行。
进程事件存在于下载和上传传输事件中。下载事件在XMLHttpRequest对象本身上被触发,就像上例一样。上传事件在XMLHttpRequest.upload对象中被触发,如下:
var oReq = new XMLHttpRequest(); oReq.upload.addEventListener("progress", updateProgress); oReq.upload.addEventListener("load", transferComplete); oReq.upload.addEventListener("error", transferFailed); oReq.upload.addEventListener("abort", transferCanceled); oReq.open();
Note: 进程事件在协议file:
中不可以使用。
Note: 从 Gecko 9.0 开始,进度事件现在可以依托于每一个传入的数据块,包括进度事件被触发前在已经接受了最后一个数据包且连接已经被关闭的情况下接收到的最后一个块。这种情况下,当该数据包的 load 事件发生时 progress 事件会被自动触发。这使你可以只关注 progress 事件就可以可靠的监测进度。
Note:在 Gecko 12.0 中,当 responseType
为 "moz-blob" 时,如果你的 progress 事件被触发,则响应的值是一个包含了接收到的数据的 Blob
。
使用 loadend
事件可以侦测到所有的三种加载结束条件(abort、load、error):
req.addEventListener("loadend", loadEnd); function loadEnd(e) { alert("The transfer finished (although we don‘t know if it succeeded or not)."); }
需要注意的是,没有方法可以确切的知道 loadend
事件接收到的信息是来自何种条件引起的操作终止;但是你可以在所有传输结束的时候使用这个事件处理。
提交表单和上传文件
XMLHttpRequest
的实例有两种方式提交表单:
- 使用 AJAX
- 使用
FormData
API
第二种方式( 使用 FormData
API )是最简单最快捷的,但是缺点是被收集的数据不是字符串形式的。
第一种方式反而是最复杂的但也是最灵活和最强大。
只使用 XMLHttpRequest
在大多数用例中,提交表单时即便不使用 FormData
API 也不会要求其他的 API。唯一的例外情况是,如果你要上传一个或多个文件,你需要额外的FileReader
API。
提交方法简介
一个 html <form>
可以用以下四种方式发送:
- 使用
POST
方法,并设置enctype
属性为application/x-www-form-urlencoded
(默认) - 使用
POST
方法,并设置enctype
属性为text/plain
- 使用
POST
方法,并设置enctype
属性为multipart/form-data
- 使用
GET
方法(这种情况下enctype
属性会被忽略)
现在,我们提交一个表单,它里面有两个字段,分别被命名为 foo
和 baz
。如果你用 POST
方法,那么服务器将会接收到一个字符串类似于下面三种情况之一,其中的区别依赖于你采用何种编码类型:
- Method:
POST
; Encoding type:application/x-www-form-urlencoded
(default):
Content-Type: application/x-www-form-urlencoded foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
- Method:
POST
; Encoding type:text/plain
:
Content-Type: text/plain foo=bar baz=The first line. The second line.
- Method:
POST
; Encoding type:multipart/form-data
:
Content-Type: multipart/form-data; boundary=---------------------------314911788813839 -----------------------------314911788813839 Content-Disposition: form-data; name="foo" bar -----------------------------314911788813839 Content-Disposition: form-data; name="baz" The first line. The second line. -----------------------------314911788813839--
相反的,如果你用 GET
方法,一个像下面这样的字符串将被简单的附加到 URL:
?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.