12
12
2 . 我们需要兼容老旧的浏览器,并且不想用 polyfills(例如为了让脚本更小)。
13
13
3 . 我们需要一些 ` fetch ` 目前无法做到的事情,比如跟踪上传进度。
14
14
15
- 这些术语听起来都很熟悉是么?如果是那么请继续阅读下面 ` XMLHttpRequest ` 内容。如果还不是很熟悉的话,那么请先阅读关于 < info:fetch-basics > 的基础内容。
15
+ 这些术语听起来都很熟悉是么?如果是那么请继续阅读下面 ` XMLHttpRequest ` 内容。如果还不是很熟悉的话,那么请先阅读关于 < info:fetch > 的基础内容。
16
16
17
- ## 基本流程
17
+ ## XMLHttpRequest 基础
18
18
19
19
XMLHttpRequest 有两种执行模式:同步(synchronous) 和 异步(asynchronous)。
20
20
21
21
我们首先来看看最常用的异步模式:
22
22
23
23
发送请求需要 3 个步骤:
24
24
25
- 1 . 创建 ` XMLHttpRequest ` 。
25
+ 1 . 创建 ` XMLHttpRequest ` :
26
26
``` js
27
- let xhr = new XMLHttpRequest (); // 没有参数
27
+ let xhr = new XMLHttpRequest (); // 构造函数没有参数
28
28
```
29
29
30
- 2. 初始化 ` XMLHttpRequest` 。
30
+ 2. 初始化 ` XMLHttpRequest` :
31
31
` ` ` js
32
32
xhr.open(method, URL, [async, user, password])
33
33
` ` `
34
34
35
35
在 ` new XMLHttpRequest` 之后我们通常调用 ` xhr.open` 函数。它指定了请求的主要参数:
36
36
37
37
- ` method` — HTTP 方法。通常是 ` "GET"` 或者 ` "POST"` 。
38
- - ` URL` — 请求的 URL 。
38
+ - ` URL` — 要执行请求(request)的 URL 字符串,可以是 [ URL ](info : url) 对象 。
39
39
- ` async` — 如果显式的设置为 ` false` ,那么请求将会以同步的方式处理,我们稍后会讨论它。
40
40
- ` user` ,` password` — HTTP 基本身份认证(如果需要的话)的登录名和密码。
41
41
@@ -121,21 +121,26 @@ xhr.onerror = function() {
121
121
` response` (以前的脚本可能用的是 ` responseText` )
122
122
: 服务器响应。
123
123
124
- 如果我们改变注意,我们可以随时终止请求。 ` xhr.abort() ` 调用可以做到 :
124
+ 我们还可以使用相应的属性指定超时(timeout)时间 :
125
125
126
126
` ` ` js
127
- xhr.abort() ; // terminate the request
127
+ xhr.timeout = 10000 ; // timeout 单位是 ms,此处即 10 秒
128
128
` ` `
129
129
130
- 它触发 ` abort ` 事件。
130
+ 如果在给定时间内请求没有成功执行,请求就会被取消,并且触发 ` timeout ` 事件。
131
131
132
- 我们还可以使用相应的属性设置超时时间:
132
+ ` ` ` ` smart header= " URL 搜索参数(URL search parameters)"
133
+ 要传递诸如 ` ?name=value` 这样的 URL 参数,并确保参数被正确编码,我们可以使用 [URL ](info: url) 对象:
133
134
134
135
` ` ` js
135
- xhr.timeout = 10000; // timeout 单位是 ms,10 秒
136
+ let url = new URL('https://google.com/search');
137
+ url.searchParams.set('q', 'test me!');
138
+
139
+ // 参数 'q' 被编码
140
+ xhr.open('GET', url); // https://google.com/search?q=test+me%21
136
141
` ` `
137
142
138
- 在给定时间内,如果请求没有成功, ` timeout ` 事件触发并且请求被取消。
143
+ ````
139
144
140
145
## 响应类型
141
146
@@ -203,10 +208,20 @@ xhr.onreadystatechange = function() {
203
208
};
204
209
` ` `
205
210
206
- 同样是基于历史原因,在非常老的代码中,你会发现它们使用的是 ` readystatechange ` 。
211
+ 你可能在古老的代码中发现 ` readystatechange ` 这样的事件监听器,它的存在是基于一些历史原因,因为在很长一段时间内都没有 ` load ` 以及其他事件 。
207
212
208
213
如今,它们已被 ` load/error/progress` 事件替代。
209
214
215
+ ## 终止请求(aborting)
216
+
217
+ 我们可以随时终止请求。调用 ` xhr.abort()` 即可:
218
+
219
+ ` ` ` js
220
+ xhr.abort(); // 终止请求
221
+ ` ` `
222
+
223
+ 它将会触发 ` abort` 事件且 ` xhr.status` 变为 ` 0` 。
224
+
210
225
## 同步请求
211
226
212
227
在 ` open` 方法中,如果第三个参数 ` async` 被设置为 ` false` ,那么请求就以同步的方式处理。
@@ -229,7 +244,7 @@ try {
229
244
}
230
245
} catch(err) { // 代替 onerror
231
246
alert("Request failed");
232
- };
247
+ }
233
248
` ` `
234
249
235
250
它可能看起来很不错,但是同步调用很少使用,因为它们会阻塞页面内(in - page)的 JavaScript 直到加载完成。在一些浏览器中,滚动可能无法正常运行。如果一个同步调用执行很长时间,浏览器可能会建议关闭“挂起”(hanging)的页面。
@@ -257,7 +272,7 @@ HTTP-headers 有三种方法:
257
272
一些请求头可能由浏览器专门管理,比如,` Referer` 和 ` Host` 。
258
273
参见 [规范](http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method) 以获取更多信息。
259
274
260
- 为了用户安全和请求的正确性,XMLHttpRequest 不允许修改它们,
275
+ 为了用户安全和请求的正确性,` XMLHttpRequest ` 不允许修改请求头。
261
276
` ` `
262
277
263
278
` ` ` ` warn header= " 不能移除 header"
@@ -300,6 +315,7 @@ HTTP-headers 有三种方法:
300
315
响应头中的换行符总是 ` "\r\n "` (不依赖于操作系统),所以我们可以很轻易地将其分割成单一的响应头部。name 和 value 之间总是会以冒号后跟空格 ` ": "` 分隔开。这在规范中已经得到修复。
301
316
302
317
因此,如果我们想要获取具有 name/ value 对的对象,我们用一点点 JS 代码来处理它们。
318
+
303
319
就像这样(假设有两个响应头具有相同的名称,那么后者会覆盖前者):
304
320
305
321
` ` ` js
@@ -324,7 +340,7 @@ let formData = new FormData([form]); // 创建对象,可以用表单元素 <fo
324
340
formData.append(name, value); // 追加一个字段
325
341
` ` `
326
342
327
- 如果需要,可以从表单中创建它,追加一个字段,然后 :
343
+ 我们可以从一个表单中创建它,如果需要的话还可以 ` 追加(append) ` 更多的字段 :
328
344
329
345
1. ` xhr.open('POST', ...)` — 使用 ` POST` 方法。
330
346
2. ` xhr.send(formData)` 发送表单到服务器。
@@ -372,19 +388,19 @@ xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
372
388
xhr.send(json);
373
389
` ` `
374
390
375
- ` .send(body)` 方法就像一个非常杂食性的动物。它可以发送几乎所有内容,包括 Blob 和 BufferSource 对象。
391
+ ` .send(body)` 方法就像一个非常杂食性的动物。它可以发送几乎所有内容,包括 ` Blob` 和 ` BufferSource` 对象。
376
392
377
393
## 上传进度(Upload progress)
378
394
379
395
` progress` 事件仅仅在下载阶段工作。
380
396
381
- 也就是说:如果 ` POST` 一些内容,` XMLHttpRequest` 首先上传我们的数据,然后下载响应数据。
397
+ 也就是说:如果 ` POST` 一些内容,` XMLHttpRequest` 首先上传我们的数据(请求体(request body)) ,然后下载响应数据。
382
398
383
- 如果我们正在上传的文件很大,这时我们肯定对追踪上传进度感兴趣。但是 ` progress ` 事件在这里并不起作用 。
399
+ 如果我们正在上传的文件很大,这时我们肯定对追踪上传进度感兴趣。但是 ` xhr.onprogress ` 在这里并不起作用 。
384
400
385
401
这里有个其他对象 ` xhr.upload` ,没有方法,专门用于上传事件。
386
402
387
- 这是其属性列表 :
403
+ XMLHttpRequest 事件和 ` xhr ` 类似,但是 ` xhr.upload ` 可以在上传阶段被触发 :
388
404
389
405
- ` loadstart` — 上传开始。
390
406
- ` progress` — 上传期间定期触发。
@@ -457,6 +473,8 @@ xhr.open('POST', 'http://anywhere.com/request');
457
473
...
458
474
` ` `
459
475
476
+ 参见 < info: fetch- crossorigin> 章节以了解更多关于 cross- origin headers 的信息。
477
+
460
478
461
479
## 总结
462
480
@@ -467,7 +485,7 @@ let xhr = new XMLHttpRequest();
467
485
468
486
xhr.open('GET', '/my/url');
469
487
470
- xhr.send(); // 对于 POST,可以发送 string 或 FormData
488
+ xhr.send();
471
489
472
490
xhr.onload = function() {
473
491
if (xhr.status != 200) { // HTTP 出错?
@@ -497,9 +515,11 @@ xhr.onerror = function() {
497
515
- ` error` — 发生连接错误,例如,域名错误。不会响应诸如 404 这类的 HTTP 错误。
498
516
- ` load` — 请求成功完成。
499
517
- ` timeout` — 请求超时被取消(仅仅发生在 timeout 被设置的情况下)。
500
- - ` loadend` — 请求完成(可能成功也可能失败)。
518
+ - ` loadend` — 在 ` load` ,` error` ,` timeout` 或者 ` abort` 之后触发。
519
+
520
+ ` error` ,` abort` ,` timeout` 和 ` load` 事件是互斥的,即一次只能有一个事件发生。
501
521
502
- 最常用的事件是加载完成(` load` ),加载失败(` error` )以及用来处理进度的 ` progress ` 。
522
+ 最常用的事件是加载完成(load completion)( ` load` ),加载失败(load failure)( ` error` ),或者我们可以只用 ` loadend ` 处理程序来检查响应,看看其发生了什么 。
503
523
504
524
我们还了解了一些其他事件:` readystatechange` 。由于历史原因,它在规范建立之前就已经出现。现如今已经没有必要使用他们了,我们可以用新的事件代替它,但是在旧的代码中仍然比较常见。
505
525
0 commit comments