diff --git a/1-js/11-async/04-promise-api/01-promise-errors-as-results/solution.md b/1-js/11-async/04-promise-api/01-promise-errors-as-results/solution.md
deleted file mode 100644
index 63e0bf1b70..0000000000
--- a/1-js/11-async/04-promise-api/01-promise-errors-as-results/solution.md
+++ /dev/null
@@ -1,44 +0,0 @@
-实际上解决方案非常简单。
-
-就像这样:
-
-```js
-Promise.all(
- fetch('https://api.github.com/users/iliakan'),
- fetch('https://api.github.com/users/remy'),
- fetch('http://no-such-url')
-)
-```
-
-这里我们有一个指向 `Promise.all` 的 `fetch(...)` promise 数组。
-
-我们不能改变 `Promise.all` 的工作方式:如果它检测到 error,就会 reject 它。因此我们需要避免任何 error 发生。相反,如果 `fetch` 发生 error,我们需要将其视为“正常”结果。
-
-就像这样:
-
-```js
-Promise.all(
- fetch('https://api.github.com/users/iliakan').catch(err => err),
- fetch('https://api.github.com/users/remy').catch(err => err),
- fetch('http://no-such-url').catch(err => err)
-)
-```
-
-换句话说,`.catch` 会对所有的 promise 产生 error,然后正常返回。根据 promise 的工作原理,只要 `.then/catch` 处理器返回值(无论是 error 对象或其他内容),执行流程就会“正常”进行。
-
-因此 `.catch` 会将 error 作为“正常”结果返回给外部的 `Promise.all`。
-
-代码如下:
-```js
-Promise.all(
- urls.map(url => fetch(url))
-)
-```
-
-可重写为:
-
-```js
-Promise.all(
- urls.map(url => fetch(url).catch(err => err))
-)
-```
diff --git a/1-js/11-async/04-promise-api/01-promise-errors-as-results/solution.view/index.html b/1-js/11-async/04-promise-api/01-promise-errors-as-results/solution.view/index.html
deleted file mode 100644
index 209e60640a..0000000000
--- a/1-js/11-async/04-promise-api/01-promise-errors-as-results/solution.view/index.html
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/1-js/11-async/04-promise-api/01-promise-errors-as-results/source.view/index.html b/1-js/11-async/04-promise-api/01-promise-errors-as-results/source.view/index.html
deleted file mode 100644
index 241b09ad4a..0000000000
--- a/1-js/11-async/04-promise-api/01-promise-errors-as-results/source.view/index.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/1-js/11-async/04-promise-api/01-promise-errors-as-results/task.md b/1-js/11-async/04-promise-api/01-promise-errors-as-results/task.md
deleted file mode 100644
index 086154c14f..0000000000
--- a/1-js/11-async/04-promise-api/01-promise-errors-as-results/task.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# 容错机制 Promise.all
-
-我们想要并行获取多个 URL。
-
-执行此操作代码如下:
-
-```js run
-let urls = [
- 'https://api.github.com/users/iliakan',
- 'https://api.github.com/users/remy',
- 'https://api.github.com/users/jeresig'
-];
-
-Promise.all(urls.map(url => fetch(url)))
- // for each response show its status
- .then(responses => { // (*)
- for(let response of responses) {
- alert(`${response.url}: ${response.status}`);
- }
- ));
-```
-
-问题是如果任何请求都失败了,那么 `Promise.all` 就会 reject error,而且所有的其他请求结果都会丢失。
-
-这并不好。
-
-修改代码会导致 `(*)` 行的 `responses` 数组包含成功响应的对象和失败时获取的 error 对象。
-
-例如,如果其中一个 URL 失效,那么就会变成这样:
-
-```js
-let urls = [
- 'https://api.github.com/users/iliakan',
- 'https://api.github.com/users/remy',
- 'http://no-such-url'
-];
-
-Promise.all(...) // your code to fetch URLs...
- // ...and pass fetch errors as members of the resulting array...
- .then(responses => {
- // 3 urls => 3 array members
- alert(responses[0].status); // 200
- alert(responses[1].status); // 200
- alert(responses[2]); // TypeError: failed to fetch (text may vary)
- });
-```
-
-P.S. 在这个任务中,你无需使用 `response.text()` 或 `response.json()` 来加载完整的请求。只要正确处理 fetch 的 error 即可。
diff --git a/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/solution.md b/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/solution.md
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/solution.view/index.html b/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/solution.view/index.html
deleted file mode 100644
index 744efd2b76..0000000000
--- a/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/solution.view/index.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/source.view/index.html b/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/source.view/index.html
deleted file mode 100644
index adb86d41fe..0000000000
--- a/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/source.view/index.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/task.md b/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/task.md
deleted file mode 100644
index 0382e5dda7..0000000000
--- a/1-js/11-async/04-promise-api/02-promise-errors-as-results-2/task.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# 用 JSON fetch 的容错处理
-
-改进之前 任务的解决方案。我们现在只需要调用 `fetch`,但要从给定的 URL 中加载 JSON。
-
-这是改进后的代码:
-
-```js run
-let urls = [
- 'https://api.github.com/users/iliakan',
- 'https://api.github.com/users/remy',
- 'https://api.github.com/users/jeresig'
-];
-
-// make fetch requests
-Promise.all(urls.map(url => fetch(url)))
- // map each response to response.json()
- .then(responses => Promise.all(
- responses.map(r => r.json())
- ))
- // show name of each user
- .then(users => { // (*)
- for(let user of users) {
- alert(user.name);
- }
- });
-```
-
-问题是如果任意请求都失败了,那么 `Promise.all` 就会 reject error,而且会丢失其他所有请求的结果。因此上述代码不易于容错,与上一个任务相同。
-
-请修改代码后,保证 `(*)` 的数组中包含请求成功解析后的 JSON 和错误的 JSON。
-
-请注意,错误可能同时发生在 `fetch`(如果请求失败)和 `response.json()`(如果响应的是无效 JSON)中。在这两种情况下,错误都会成为结果对象的成员。
-
-这两种情况沙箱都有。
diff --git a/1-js/11-async/04-promise-api/article.md b/1-js/11-async/04-promise-api/article.md
deleted file mode 100644
index 448d78cc97..0000000000
--- a/1-js/11-async/04-promise-api/article.md
+++ /dev/null
@@ -1,202 +0,0 @@
-# Promise API
-
-在 `Promise` 类中,有 4 中静态方法。我们在这里做下简单介绍。
-
-## Promise.resolve
-
-语法:
-
-```js
-let promise = Promise.resolve(value);
-```
-
-根据给定的 `value` 值返回 resolved promise。
-
-等价于:
-
-```js
-let promise = new Promise(resolve => resolve(value));
-```
-
-当我们已经有一个 value 的时候,就会使用该方法,但希望将它“封装”进 promise。
-
-例如,下面的 `loadCached` 函数会获取 `url` 并记住结果,以便以后对同一 URL 进行调用时可以立即返回:
-
-```js
-function loadCached(url) {
- let cache = loadCached.cache || (loadCached.cache = new Map());
-
- if (cache.has(url)) {
-*!*
- return Promise.resolve(cache.get(url)); // (*)
-*/!*
- }
-
- return fetch(url)
- .then(response => response.text())
- .then(text => {
- cache[url] = text;
- return text;
- });
-}
-```
-
-我们可以使用 `loadCached(url).then(…)`,因为函数保证会返回一个 promise。这是 `Promise.resolve` 在 `(*)` 行的目的:它确保了接口的统一性。我们可以在 `loadCached` 之后使用 `.then`。
-
-## Promise.reject
-
-语法:
-
-```js
-let promise = Promise.reject(error);
-```
-
-创建一个带有 `error` 的 rejected promise。
-
-就像这样:
-
-```js
-let promise = new Promise((resolve, reject) => reject(error));
-```
-
-我们会在此讨论它的完整性,但在实际工作中,我们很少这样使用。
-
-## Promise.all
-
-该方法并行运行多个 promise,并等待所有 promise 准备就绪。
-
-语法:
-
-```js
-let promise = Promise.all(iterable);
-```
-
-它需要一个带有 promise 的 `iterable` 对象,技术上来说,它是可以迭代的,但通常情况下,它只是一个数组,而且会返回一个新的 promise。新的 promise 是在所有 promise 都被解决并拥有一个存放结果的数组之后才出现的。
-
-例如,下面的 `Promise.all` 在 3 秒之后被处理,然后它的结果就是一个 `[1, 2, 3]` 数组:
-
-```js run
-Promise.all([
- new Promise((resolve, reject) => setTimeout(() => resolve(1), 3000)), // 1
- new Promise((resolve, reject) => setTimeout(() => resolve(2), 2000)), // 2
- new Promise((resolve, reject) => setTimeout(() => resolve(3), 1000)) // 3
-]).then(alert); // 1,2,3 when promises are ready: each promise contributes an array member
-```
-
-注意,它们的相对顺序是相同的。尽管第一个 promise 需要很长的时间来解决,但它仍然是结果数组中的第一个。
-
-常见技巧是将一组作业数据映射到一个 promise 数组,然后再将它们封装进 `Promise.all`。
-
-例如,我们有一个存储 URL 的数组,我们就可以像这样来获取它们:
-
-```js run
-let urls = [
- 'https://api.github.com/users/iliakan',
- 'https://api.github.com/users/remy',
- 'https://api.github.com/users/jeresig'
-];
-
-// map every url to the promise fetch(github url)
-let requests = urls.map(url => fetch(url));
-
-// Promise.all waits until all jobs are resolved
-Promise.all(requests)
- .then(responses => responses.forEach(
- response => alert(`${response.url}: ${response.status}`)
- ));
-```
-
-一个更真实的示例是通过用户名来为 GitHub 用户数组获取用户信息(或者我们可以通过他们的 id 来获取一系列商品,逻辑都是一样的):
-
-```js run
-let names = ['iliakan', 'remy', 'jeresig'];
-
-let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));
-
-Promise.all(requests)
- .then(responses => {
- // all responses are ready, we can show HTTP status codes
- for(let response of responses) {
- alert(`${response.url}: ${response.status}`); // shows 200 for every url
- }
-
- return responses;
- })
- // map array of responses into array of response.json() to read their content
- .then(responses => Promise.all(responses.map(r => r.json())))
- // all JSON answers are parsed: "users" is the array of them
- .then(users => users.forEach(user => alert(user.name)));
-```
-
-如果任何 promise 为 rejected,`Promise.all` 就会立即以 error reject。
-
-例如:
-
-
-```js run
-Promise.all([
- new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
-*!*
- new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
-*/!*
- new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
-]).catch(alert); // 错误:喔!
-```
-
-这里的第二个 promise 在两秒内为 reject。这立即导致了对 `Promise.all` 的 reject。因此 `.catch` 被执行:避免 error 成为整个 `Promise.all` 的结果。
-
-重要的细节是 promise 没有提供 "cancel" 或 "abort" 执行方法。因此,其他 promise 会继续执行,并最终为 settle,但它们的结果会被忽略。
-
-有避免这种情况的方法:我们可以编写额外的代码到 `clearTimeout`(或在出现 error 时取消)promise,或者我们可以将 error 作为结果数组中的成员显示出来(参阅本章下的 task)。
-
-````smart header="`Promise.all(iterable)` 允许在 `iterable` 中无 promise"
-通常 `Promise.all(iterable)` 接受可迭代的 promise(大多数情况是数组)。但如果这些对象中的任何一个不是 promise,它就会被封装进 `Promise.resolve`。
-
-例如。这里的结果是 `[1, 2, 3]`:
-
-```js run
-Promise.all([
- new Promise((resolve, reject) => {
- setTimeout(() => resolve(1), 1000)
- }),
- 2, // treated as Promise.resolve(2)
- 3 // treated as Promise.resolve(3)
-]).then(alert); // 1, 2, 3
-```
-
-因此我们可以在方便的时候将非 promise 值传递给 `Promise.all`。
-
-````
-
-## Promise.race
-
-与 `Promise.all` 类似,所有的 promise 都是可迭代的,但不会等待所有都完成 —— 只等待第一个完成(或者有 error),然后继续执行。
-
-语法是:
-
-```js
-let promise = Promise.race(iterable);
-```
-
-例如,这里的结果回事 `1`:
-
-```js run
-Promise.race([
- new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
- new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
- new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
-]).then(alert); // 1
-```
-
-因此,第一个结果/错误会成为整个 `Promise.race` 的结果。在第一个 promise "wins the race" 被解决后,所有的深层的结果/错误都会被忽略。
-
-## 总结
-
-`Promise` 类有 4 中静态方法:
-
-1. `Promise.resolve(value)` —— 根据给定值返回 resolved promise,
-2. `Promise.reject(error)` —— 根据给定错误返回 rejected promise,
-3. `Promise.all(promises)` —— 等待所有的 promise 为 resolve 时返回存放它们结果的数组。如果任意给定的 promise 为 reject,那么它就会变成 `Promise.all` 的错误结果,所以所有的其他结果都会被忽略。
-4. `Promise.race(promises)` —— 等待第一个 promise 被解决,其结果/错误即为结果。
-
-这四个方法中,`Promise.all` 在实战中使用的最多。
diff --git a/1-js/11-async/05-promise-api/article.md b/1-js/11-async/05-promise-api/article.md
new file mode 100644
index 0000000000..bcfa4a1a7f
--- /dev/null
+++ b/1-js/11-async/05-promise-api/article.md
@@ -0,0 +1,291 @@
+# Promise API
+
+在 `Promise` 类中,有 5 种静态方法。我们在这里简单介绍下它们的使用场景。
+
+## Promise.resolve
+
+语法:
+
+```js
+let promise = Promise.resolve(value);
+```
+
+根据给定的 `value` 值返回 resolved promise。
+
+等价于:
+
+```js
+let promise = new Promise(resolve => resolve(value));
+```
+
+当我们已经有一个 value 的时候,就会使用该方法,但希望将它“封装”进 promise。
+
+例如,下面的 `loadCached` 函数会获取 `url` 并记住结果,以便以后对同一 URL 进行调用时可以立即返回:
+
+```js
+function loadCached(url) {
+ let cache = loadCached.cache || (loadCached.cache = new Map());
+
+ if (cache.has(url)) {
+*!*
+ return Promise.resolve(cache.get(url)); // (*)
+*/!*
+ }
+
+ return fetch(url)
+ .then(response => response.text())
+ .then(text => {
+ cache.set(url,text);
+ return text;
+ });
+}
+```
+
+我们可以使用 `loadCached(url).then(…)`,因为该函数必定返回一个 promise。这是 `Promise.resolve` 在 `(*)` 行的目的:它确保了接口的统一性。我们可以在 `loadCached` 之后使用 `.then`。
+
+## Promise.reject
+
+语法:
+
+```js
+let promise = Promise.reject(error);
+```
+
+创建一个带有 `error` 的 rejected promise。
+
+就像这样:
+
+```js
+let promise = new Promise((resolve, reject) => reject(error));
+```
+
+我们会在此讨论它的完整性,但在实际工作中,我们很少这样使用。
+
+## Promise.all
+
+假设我想要并行执行多个 promise,并等待所有 promise 准备就绪。
+
+例如,并行下载几个 URL 并等到所有内容都下载完毕后才开始处理它们。
+
+这就是 `Promise.all` 的用途:
+
+语法:
+
+```js
+let promise = Promise.all([...promises...]);
+```
+
+它需要一个 promise 的数组作为其参数(严格来说可以是任何可迭代对象,但通常都是数组)并返回一个新的 promise。
+
+当所有给定的 promise 都被处理并以数组的形式呈现其结果时,新的 promise 也就被 resolve。
+
+例如,下面的 `Promise.all` 在 3 秒之后被处理,然后它的结果就是一个 `[1, 2, 3]` 数组:
+
+```js run
+Promise.all([
+ new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
+ new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
+ new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
+]).then(alert); // 1,2,3 当 promise 就绪:每一个 promise 即成为数组中的一员
+```
+
+请注意,它们的相对顺序是相同的。即使第一个 promise 需要很长的时间来 resolve,但它仍然是结果数组中的第一个。
+
+常见技巧是将一组作业数据映射到一个 promise 数组,然后再将它们封装进 `Promise.all`。
+
+例如,假设我们有一个存储 URL 的数组,我们就可以像这样来获取它们:
+
+```js run
+let urls = [
+ 'https://api.github.com/users/iliakan',
+ 'https://api.github.com/users/remy',
+ 'https://api.github.com/users/jeresig'
+];
+
+// 将每个 url 映射到 fetch 的 promise 中
+let requests = urls.map(url => fetch(url));
+
+// Promise.all 等待所有作业都被 resolve
+Promise.all(requests)
+ .then(responses => responses.forEach(
+ response => alert(`${response.url}: ${response.status}`)
+ ));
+```
+
+一个更真实的示例是通过用户名来为一组 GitHub 用户获取他们的信息(或者我们可以通过他们的 id 来获取一系列商品,逻辑都是一样的):
+
+```js run
+let names = ['iliakan', 'remy', 'jeresig'];
+
+let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));
+
+Promise.all(requests)
+ .then(responses => {
+ // 所有响应都就绪时,我们可以显示 HTTP 状态码
+ for(let response of responses) {
+ alert(`${response.url}: ${response.status}`); // 每个 url 都显示 200
+ }
+
+ return responses;
+ })
+ // 映射 response 数组到 response.json() 中以读取它们的内容
+ .then(responses => Promise.all(responses.map(r => r.json())))
+ // 所有 JSON 结果都被解析:“users” 是它们的数组
+ .then(users => users.forEach(user => alert(user.name)));
+```
+
+**如果任意一个 promise 为 reject,`Promise.all` 返回的 promise 就会立即 reject 这个错误。**
+
+例如:
+
+```js run
+Promise.all([
+ new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
+*!*
+ new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
+*/!*
+ new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
+]).catch(alert); // Error: Whoops!
+```
+
+这里的第二个 promise 在两秒内被 reject。这立即导致了对 `Promise.all` 的 reject。因此 `.catch` 被执行:reject 的错误成为整个 `Promise.all` 的结果。
+
+```warn header="如果出现错误,其他 promise 就会被忽略"
+如果其中一个 promise 被 reject,`Promise.all` 就会立即被 reject 并忽略所有列表中其他的 promise。它们的结果也被忽略。
+
+例如,像上面例子中提到的那样,如果同时进行多个 `fetch` 操作,其中一个失败,其他的 `fetch` 操作仍然会继续执行,但是 `Promise.all` 会忽略它们。它们可能已经解决了某些问题,但是结果将会被忽略。
+
+没有什么方法能取消 `Promise.all`,因为 promise 中没有 “cancellation” 这类概念。在 [其他章节](info:fetch-abort) 我们将会讨论可以“取消” promise 的 `AbortController`,但它不是 Promise API 的一部分。
+```
+
+````smart header="`Promise.all(iterable)` 允许“迭代”中的非 promise(non-promise)的 \“常规\” 值"
+通常,`Promise.all(...)` 接受可迭代的 promise 集合(大部分情况下是数组)。但是如果这些对象中的任意一个不是 promise,它将会被直接包装进 `Promise.resolve`。
+
+例如,这里的结果是 `[1, 2, 3]`:
+
+```js run
+Promise.all([
+ new Promise((resolve, reject) => {
+ setTimeout(() => resolve(1), 1000)
+ }),
+ 2, // 视为 Promise.resolve(2)
+ 3 // 视为 Promise.resolve(3)
+]).then(alert); // 1, 2, 3
+```
+
+所以我们可以很方便的将准备好的值传递给 `Promise.all`。
+````
+
+## Promise.allSettled
+
+[recent browser="new"]
+
+如果任意 promise reject,`Promise.all` 整个将会 reject。当我们需要*所有*结果来做些什么的时候,这样的情况就很好:
+
+```js
+Promise.all([
+ fetch('/template.html'),
+ fetch('/style.css'),
+ fetch('/data.json')
+]).then(render); // render 方法需要上面所有数据
+```
+
+`Promise.allSettled` 等待所有的 promise 都被处理:即使其中一个 reject,它仍然会等待其他的 promise。处理完成后的数组有:
+
+- `{status:"fulfilled", value:result}` 对于成功的响应,
+- `{status:"rejected", reason:error}` 对于错误的响应。
+
+例如,我们想要获取多个用户的信息。即使其中一个请求失败,我们仍然对其他的感兴趣。
+
+让我们使用 `Promise.allSettled`:
+
+```js run
+let urls = [
+ 'https://api.github.com/users/iliakan',
+ 'https://api.github.com/users/remy',
+ 'https://no-such-url'
+];
+
+Promise.allSettled(urls.map(url => fetch(url)))
+ .then(results => { // (*)
+ results.forEach((result, num) => {
+ if (result.status == "fulfilled") {
+ alert(`${urls[num]}: ${result.value.status}`);
+ }
+ if (result.status == "rejected") {
+ alert(`${urls[num]}: ${result.reason}`);
+ }
+ });
+ });
+```
+
+上面的 `(*)` 行,`results` 将会是:
+```js
+[
+ {status: 'fulfilled', value: ...response...},
+ {status: 'fulfilled', value: ...response...},
+ {status: 'rejected', reason: ...error object...}
+]
+```
+
+因此,对于每个 promise,我们都能获取其状态(status)和 `value/reason`。
+
+### Polyfill
+
+如果浏览器不支持 `Promise.allSettled`,使用 polyfill 很容易让其支持:
+
+```js
+if(!Promise.allSettled) {
+ Promise.allSettled = function(promises) {
+ return Promise.all(promises.map(p => Promise.resolve(p).then(v => ({
+ state: 'fulfilled',
+ value: v,
+ }), r => ({
+ state: 'rejected',
+ reason: r,
+ }))));
+ };
+}
+```
+
+在这段代码中,`promises.map` 获取输入值,并使用 `p => Promise.resolve(p)` 将该值转换为 promise(以防传递了非 promise),然后向其添加 `.then` 处理器。
+
+这个处理器将成功的结果 `v` 转换为 `{state:'fulfilled', value:v}`,将错误的结果 `r` 转换为 `{state:'rejected', reason:r}`。这正是 `Promise.allSettled` 的格式。
+
+然后我们就可以使用 `Promise.allSettled` 来获取结果或*所有*给出的 promise,即使其中一些被 reject。
+
+## Promise.race
+
+与 `Promise.all` 类似,它接受一个可迭代的 promise 集合,但是它只等待第一个完成(或者 error)而不会等待所有都完成,然后继续执行。
+
+语法:
+
+```js
+let promise = Promise.race(iterable);
+```
+
+例如,这里的结果会是 `1`:
+
+```js run
+Promise.race([
+ new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
+ new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
+ new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
+]).then(alert); // 1
+```
+
+因此,第一个结果/错误会成为整个 `Promise.race` 的结果。在第一个 promise 被解决(“赢得比赛[wins the race]”)后,所有后面的结果/错误都会被忽略。
+
+## 总结
+
+`Promise` 类有 5 种静态方法:
+
+1. `Promise.resolve(value)` - 根据给定值返回 resolved promise。
+2. `Promise.reject(error)` - 根据给定错误返回 rejected promise。
+3. `Promise.all(promises)` - 等待所有的 promise 为 resolve 时返回存放它们结果的数组。如果任意给定的 promise 为 reject,那么它就会变成 `Promise.all` 的错误结果,所有的其他结果都会被忽略。
+4. `Promise.allSettled(promises)` (新方法) - 等待所有 promise resolve 或者 reject,并以对象形式返回它们结果数组:
+ - `state`:`‘fulfilled’` 或 `‘rejected’`
+ - `value`(如果 fulfilled)或 `reason`(如果 rejected)
+5. `Promise.race(promises)` - 等待第一个 promise 被解决,其结果/错误即为结果。
+
+这五个方法中,`Promise.all` 在实战中使用的最多。
diff --git a/1-js/11-async/04-promise-api/head.html b/1-js/11-async/05-promise-api/head.html
similarity index 100%
rename from 1-js/11-async/04-promise-api/head.html
rename to 1-js/11-async/05-promise-api/head.html
diff --git a/1-js/11-async/04-promise-api/iliakan.json b/1-js/11-async/05-promise-api/iliakan.json
similarity index 100%
rename from 1-js/11-async/04-promise-api/iliakan.json
rename to 1-js/11-async/05-promise-api/iliakan.json
diff --git a/1-js/11-async/04-promise-api/one.js b/1-js/11-async/05-promise-api/one.js
similarity index 100%
rename from 1-js/11-async/04-promise-api/one.js
rename to 1-js/11-async/05-promise-api/one.js
diff --git a/1-js/11-async/04-promise-api/two.js b/1-js/11-async/05-promise-api/two.js
similarity index 100%
rename from 1-js/11-async/04-promise-api/two.js
rename to 1-js/11-async/05-promise-api/two.js