Skip to content

Commit f93ab3a

Browse files
authored
Merge pull request #427 from lycheeEng/5-network-08-xmlhttprequest
Update: 5-network/08-xmlhttprequest
2 parents 7e6307b + 3754064 commit f93ab3a

File tree

13 files changed

+43
-23
lines changed

13 files changed

+43
-23
lines changed

5-network/07-xmlhttprequest/article.md renamed to 5-network/08-xmlhttprequest/article.md

+43-23
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,30 @@
1212
2. 我们需要兼容老旧的浏览器,并且不想用 polyfills(例如为了让脚本更小)。
1313
3. 我们需要一些 `fetch` 目前无法做到的事情,比如跟踪上传进度。
1414

15-
这些术语听起来都很熟悉是么?如果是那么请继续阅读下面 `XMLHttpRequest` 内容。如果还不是很熟悉的话,那么请先阅读关于 <info:fetch-basics> 的基础内容。
15+
这些术语听起来都很熟悉是么?如果是那么请继续阅读下面 `XMLHttpRequest` 内容。如果还不是很熟悉的话,那么请先阅读关于 <info:fetch> 的基础内容。
1616

17-
## 基本流程
17+
## XMLHttpRequest 基础
1818

1919
XMLHttpRequest 有两种执行模式:同步(synchronous) 和 异步(asynchronous)。
2020

2121
我们首先来看看最常用的异步模式:
2222

2323
发送请求需要 3 个步骤:
2424

25-
1. 创建 `XMLHttpRequest`
25+
1. 创建 `XMLHttpRequest`
2626
```js
27-
let xhr = new XMLHttpRequest(); // 没有参数
27+
let xhr = new XMLHttpRequest(); // 构造函数没有参数
2828
```
2929

30-
2. 初始化 `XMLHttpRequest`
30+
2. 初始化 `XMLHttpRequest`
3131
```js
3232
xhr.open(method, URL, [async, user, password])
3333
```
3434

3535
`new XMLHttpRequest` 之后我们通常调用 `xhr.open` 函数。它指定了请求的主要参数:
3636

3737
- `method`HTTP 方法。通常是 `"GET"` 或者 `"POST"`
38-
- `URL`请求的 URL
38+
- `URL`要执行请求(request)的 URL 字符串,可以是 [URL](info:url) 对象
3939
- `async` — 如果显式的设置为 `false`,那么请求将会以同步的方式处理,我们稍后会讨论它。
4040
- `user``password`HTTP 基本身份认证(如果需要的话)的登录名和密码。
4141

@@ -121,21 +121,26 @@ xhr.onerror = function() {
121121
`response`(以前的脚本可能用的是 `responseText`
122122
: 服务器响应。
123123

124-
如果我们改变注意,我们可以随时终止请求。`xhr.abort()` 调用可以做到
124+
我们还可以使用相应的属性指定超时(timeout)时间
125125

126126
```js
127-
xhr.abort(); // terminate the request
127+
xhr.timeout = 10000; // timeout 单位是 ms,此处即 10 秒
128128
```
129129

130-
它触发 `abort` 事件。
130+
如果在给定时间内请求没有成功执行,请求就会被取消,并且触发 `timeout` 事件。
131131

132-
我们还可以使用相应的属性设置超时时间:
132+
````smart header="URL 搜索参数(URL search parameters)"
133+
要传递诸如 `?name=value` 这样的 URL 参数,并确保参数被正确编码,我们可以使用 [URL](info:url) 对象:
133134

134135
```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
136141
```
137142

138-
在给定时间内,如果请求没有成功,`timeout` 事件触发并且请求被取消。
143+
````
139144

140145
## 响应类型
141146

@@ -203,10 +208,20 @@ xhr.onreadystatechange = function() {
203208
};
204209
```
205210

206-
同样是基于历史原因,在非常老的代码中,你会发现它们使用的是 `readystatechange`
211+
你可能在古老的代码中发现 `readystatechange` 这样的事件监听器,它的存在是基于一些历史原因,因为在很长一段时间内都没有 `load` 以及其他事件
207212

208213
如今,它们已被 `load/error/progress` 事件替代。
209214

215+
## 终止请求(aborting)
216+
217+
我们可以随时终止请求。调用 `xhr.abort()` 即可:
218+
219+
```js
220+
xhr.abort(); // 终止请求
221+
```
222+
223+
它将会触发 `abort` 事件且 `xhr.status` 变为 `0`
224+
210225
## 同步请求
211226

212227
`open` 方法中,如果第三个参数 `async` 被设置为 `false`,那么请求就以同步的方式处理。
@@ -229,7 +244,7 @@ try {
229244
}
230245
} catch(err) { // 代替 onerror
231246
alert("Request failed");
232-
};
247+
}
233248
```
234249

235250
它可能看起来很不错,但是同步调用很少使用,因为它们会阻塞页面内(in-page)的 JavaScript 直到加载完成。在一些浏览器中,滚动可能无法正常运行。如果一个同步调用执行很长时间,浏览器可能会建议关闭“挂起”(hanging)的页面。
@@ -257,7 +272,7 @@ HTTP-headers 有三种方法:
257272
一些请求头可能由浏览器专门管理,比如,`Referer``Host`
258273
参见 [规范](http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method) 以获取更多信息。
259274
260-
为了用户安全和请求的正确性,XMLHttpRequest 不允许修改它们,
275+
为了用户安全和请求的正确性,`XMLHttpRequest` 不允许修改请求头。
261276
```
262277

263278
````warn header="不能移除 header"
@@ -300,6 +315,7 @@ HTTP-headers 有三种方法:
300315
响应头中的换行符总是 `"\r\n"`(不依赖于操作系统),所以我们可以很轻易地将其分割成单一的响应头部。name 和 value 之间总是会以冒号后跟空格 `": "` 分隔开。这在规范中已经得到修复。
301316

302317
因此,如果我们想要获取具有 name/value 对的对象,我们用一点点 JS 代码来处理它们。
318+
303319
就像这样(假设有两个响应头具有相同的名称,那么后者会覆盖前者):
304320

305321
```js
@@ -324,7 +340,7 @@ let formData = new FormData([form]); // 创建对象,可以用表单元素 <fo
324340
formData.append(name, value); // 追加一个字段
325341
```
326342

327-
如果需要,可以从表单中创建它,追加一个字段,然后
343+
我们可以从一个表单中创建它,如果需要的话还可以`追加(append)`更多的字段
328344

329345
1. `xhr.open('POST', ...)` — 使用 `POST` 方法。
330346
2. `xhr.send(formData)` 发送表单到服务器。
@@ -372,19 +388,19 @@ xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
372388
xhr.send(json);
373389
```
374390

375-
`.send(body)` 方法就像一个非常杂食性的动物。它可以发送几乎所有内容,包括 BlobBufferSource 对象。
391+
`.send(body)` 方法就像一个非常杂食性的动物。它可以发送几乎所有内容,包括 `Blob``BufferSource` 对象。
376392

377393
## 上传进度(Upload progress)
378394

379395
`progress` 事件仅仅在下载阶段工作。
380396

381-
也就是说:如果 `POST` 一些内容,`XMLHttpRequest` 首先上传我们的数据,然后下载响应数据。
397+
也就是说:如果 `POST` 一些内容,`XMLHttpRequest` 首先上传我们的数据(请求体(request body)),然后下载响应数据。
382398

383-
如果我们正在上传的文件很大,这时我们肯定对追踪上传进度感兴趣。但是 `progress` 事件在这里并不起作用
399+
如果我们正在上传的文件很大,这时我们肯定对追踪上传进度感兴趣。但是 `xhr.onprogress` 在这里并不起作用
384400

385401
这里有个其他对象 `xhr.upload`,没有方法,专门用于上传事件。
386402

387-
这是其属性列表
403+
XMLHttpRequest 事件和 `xhr` 类似,但是 `xhr.upload` 可以在上传阶段被触发
388404

389405
- `loadstart` — 上传开始。
390406
- `progress` — 上传期间定期触发。
@@ -457,6 +473,8 @@ xhr.open('POST', 'http://anywhere.com/request');
457473
...
458474
```
459475

476+
参见 <info:fetch-crossorigin> 章节以了解更多关于 cross-origin headers 的信息。
477+
460478

461479
## 总结
462480

@@ -467,7 +485,7 @@ let xhr = new XMLHttpRequest();
467485
468486
xhr.open('GET', '/my/url');
469487
470-
xhr.send(); // 对于 POST,可以发送 string 或 FormData
488+
xhr.send();
471489
472490
xhr.onload = function() {
473491
if (xhr.status != 200) { // HTTP 出错?
@@ -497,9 +515,11 @@ xhr.onerror = function() {
497515
- `error` — 发生连接错误,例如,域名错误。不会响应诸如 404 这类的 HTTP 错误。
498516
- `load` — 请求成功完成。
499517
- `timeout` — 请求超时被取消(仅仅发生在 timeout 被设置的情况下)。
500-
- `loadend` — 请求完成(可能成功也可能失败)。
518+
- `loadend` — 在 `load``error``timeout` 或者 `abort` 之后触发。
519+
520+
`error``abort``timeout``load` 事件是互斥的,即一次只能有一个事件发生。
501521

502-
最常用的事件是加载完成(`load`),加载失败(`error`以及用来处理进度的 `progress`
522+
最常用的事件是加载完成(load completion)(`load`),加载失败(load failure)(`error`,或者我们可以只用 `loadend` 处理程序来检查响应,看看其发生了什么
503523

504524
我们还了解了一些其他事件:`readystatechange`。由于历史原因,它在规范建立之前就已经出现。现如今已经没有必要使用他们了,我们可以用新的事件代替它,但是在旧的代码中仍然比较常见。
505525

0 commit comments

Comments
 (0)