关于Promise你需要知道的一切

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 是 JavaScript 中的对异步操作最佳的 API 之一。作为JavaScript开发人员,需要熟练掌握 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 相关的知识。本文就来总结一下这些知识点,先来回顾 JavaScript 过去异步操作的处理方式?然后详细介绍 Promises 对象及相关的方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"现在先来了解一下 JavaScript 异步概念。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"异步回顾","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"什么是异步?如果在函数返回的时候,调用者还不能获取到预期结果,而是将来通过一定的方式得到(例如回调函数),这函数就是异步。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"异步回调","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"异步回调,就是常见的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"callback","attrs":{}}],"attrs":{}},{"type":"text","text":" ,这是过去在 JavaScript 中处理异步操作的常见方式,如 AJAX ,发起一个HTTP请求,具体服务器什么时候返回响应数据取决于客户的环境,存在很多不确定因素,这时采用回调函数可以在返回响应数据的时候触发回调函数。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这种方式当有多个请求的情况,后续请求需要等待前面请求的响应数据的时候,就会出现常见的回调地狱。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const asyncMessage = function (message, callback) {\n setTimeout(function () {\n console.log(message);\n callback();\n }, 1000);\n};\n\nasyncMessage(\"title\", function () {\n asyncMessage(\"cate\", function () {\n asyncMessage(\"content\", function () {\n console.log(\"detail\");\n });\n });\n});\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"出现回调地狱将会给项目开发带来很多问题:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"会导致逻辑混乱,耦合性高,改动一处就会导致全部变动,嵌套多时,BUG问题难以发现。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不能使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"try...catch","attrs":{}}],"attrs":{}},{"type":"text","text":" 来捕获异常。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不能使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"return","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回真实数据","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"为了避免回调地狱的出现,后来就有了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 对象。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Promise 的工作方式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 对象是一个可以从异步函数同步返回的对象,它将处于 3 种可能的状态之一:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"fulfilled","attrs":{}}],"attrs":{}},{"type":"text","text":" 已兑现: ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"onFulfilled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 将被调用,即操作完成(例如,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve()","attrs":{}}],"attrs":{}},{"type":"text","text":" 被调用)","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 已拒绝: ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"onRejected()","attrs":{}}],"attrs":{}},{"type":"text","text":" 将被调用,即操作失败(例如,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"reject()","attrs":{}}],"attrs":{}},{"type":"text","text":" 被调用)","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"pending","attrs":{}}],"attrs":{}},{"type":"text","text":" 待定:初始状态,既没有被兑现,也没有被拒绝","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 没有挂起(它已被解决或拒绝),它就会被解决。有时使用已解决和已解决表示同一件事:不是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"pending","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 一旦确定,就不能再重新确定,再次调用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve()","attrs":{}}],"attrs":{}},{"type":"text","text":" 或","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" reject()","attrs":{}}],"attrs":{}},{"type":"text","text":" 将没有效果。一个已确定的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的具有不可变性。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"对于 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的状态监控可以使用承诺链,即在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"fulfilled","attrs":{}}],"attrs":{}},{"type":"text","text":" 已兑现的状态可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"then","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法可以获取已兑现的结果,在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 已拒绝状态使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"catch","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法获取拒绝的原因。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const myPromise = new Promise(myExecutorFunc)\n .then(handleFulfilledA)\n .then(handleFulfilledB)\n .then(handleFulfilledC)\n .catch(handleRejectedAny);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看起来比 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"callback","attrs":{}}],"attrs":{}},{"type":"text","text":" 的方式优雅一点,对于需要发起多次HTTP请求才能完整呈现的需求,代码如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const getPost = () => fetch(\"https://jsonplaceholder.typicode.com/posts/1\");\nconst getAuthor = (id) =>\n fetch(\"https://jsonplaceholder.typicode.com/users/\" + id);\nconst getComment = (id) =>\n fetch(\"https://jsonplaceholder.typicode.com/users/\" + id);\n\ngetPost() // #1.fetch post\n .then((postResponse) => postResponse.json()) // #2. get & return post json\n .then((postResponse) =>\n getAuthor(postResponse.id) // #3. fetch author\n .then((authorResponse) =>\n authorResponse\n .json() // #4 get & return author json\n .then((authorResponse) =>\n getComment(postResponse.id) // #5 fetch comment\n .then((commentResponse) => commentResponse.json()) // #6 get & return comment json\n .then((commentResponse) => {\n // #7 time to combine all results\n return {\n postResponse,\n authorResponse,\n commentResponse,\n }; // #8 combine & return all reponses\n })\n )\n )\n .then((results) => {\n // #9 read all responses\n console.log(results.postResponse);\n console.log(results.authorResponse);\n console.log(results.commentResponse);\n })\n )\n .catch((error) => console.log(error)); // # 10 error handling\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面代码是否有种似曾相识的感觉,原本是为了解决回调地狱,但似乎理想跟现实还是有差距。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"于是 ES2021 为 Promise 对象增加新的特征,其中包括:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Promise.any()","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.any(promises)","attrs":{}}],"attrs":{}},{"type":"text","text":" 能够并行运行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":",并解析为 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 列表中第一个成功解析的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的值。需要注意的是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any() ","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法依然是实验性的,尚未被所有的浏览器完全支持。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面来看看 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 是如何工作的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.工作原理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 可用于以并行和竞争方式执行独立的异步操作,以获取任何第一个完成的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的值。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"该函数接受一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组(通常为一个可迭代对象)作为参数,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const anyPromise = Promise.any(promises);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"当输入 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 中的第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被执行完成时,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"anyPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 会立即解析为该 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的值。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b0/b0ba78555518258338891be0a96d6e72.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"then","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法提取第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的值:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"anyPromise.then((firstValue) => {\n firstValue; // 第一个 promise 完成后返回的值\n});\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"async/await","attrs":{}}],"attrs":{}},{"type":"text","text":" 语法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const firstValue = await anyPromise;\nconsole.log(firstValue); // 第一个 promise 完成后返回的值\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 与任何第一个执行的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 一起执行。即使某些 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":",这些 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejections","attrs":{}}],"attrs":{}},{"type":"text","text":" 也将会被忽略。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b6/b64a79f48c45d55fe55775a6837bd3e9.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,如果输入数组中的所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 都被拒绝,或者输入数组为空,那么","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 会 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 包含输入的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 执行的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejection","attrs":{}}],"attrs":{}},{"type":"text","text":" 错误原因集合。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/40/40daca274089ec9cfe207e70f7856624.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2. 使用指南","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"现在来深入介绍一下 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":", 在这之前,先来定义 2 个简单的函数。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"函数 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolveTimeout(value, delay)","attrs":{}}],"attrs":{}},{"type":"text","text":" 将返回一个在经过 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"delay","attrs":{}}],"attrs":{}},{"type":"text","text":" 时间后有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function resolveTimeout(value, delay) {\n return new Promise((resolve) => setTimeout(() => resolve(value), delay));\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"函数 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejectTimeout(reason, delay)","attrs":{}}],"attrs":{}},{"type":"text","text":" 将返回一个在经过 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"delay","attrs":{}}],"attrs":{}},{"type":"text","text":" 时间后有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"reject","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function rejectTimeout(reason, delay) {\n return new Promise((r, reject) => setTimeout(() => reject(reason), delay));\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下来使用上面定义的2个辅助函数来试试 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.1 完成所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面尝试运行第一个解析列表:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function resolveTimeout(value, delay) {\n return new Promise((resolve) => setTimeout(() => resolve(value), delay));\n}\nfunction rejectTimeout(reason, delay) {\n return new Promise((r, reject) => setTimeout(() => reject(reason), delay));\n}\nconst fruits = [\"potatoes\", \"tomatoes\"];\nconst vegetables = [\"oranges\", \"apples\"];\nconst promise = Promise.any([\n resolveTimeout(fruits, 1000),\n resolveTimeout(vegetables, 2000),\n]);\n\n// 等待...\nconst list = async () => {\n const result = await promise;\n console.log(result);\n};\n\n// 1 秒之后\nlist(); // ['potatoes', 'tomatoes']\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"promise .any([…])","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回一个在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"1秒内","attrs":{}}],"attrs":{}},{"type":"text","text":" 解析到数组 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"fruits","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":",因为解析fruits的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 先执行完成。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二个是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" 2秒内","attrs":{}}],"attrs":{}},{"type":"text","text":" 解析到数组 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"vegetables","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":",其值将被忽略。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.2 一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"将上面第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 出现异常被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,如下代码:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function resolveTimeout(value, delay) {\n return new Promise((resolve) => setTimeout(() => resolve(value), delay));\n}\nfunction rejectTimeout(reason, delay) {\n return new Promise((r, reject) => setTimeout(() => reject(reason), delay));\n}\nconst vegetables = [\"oranges\", \"apples\"];\n\nconst promise = Promise.any([\n rejectTimeout(new Error(\"fruits is empty\"), 1000),\n resolveTimeout(vegetables, 2000),\n]);\n\n// 等待...\nconst list = async () => {\n const result = await promise;\n console.log(result);\n};\n\n// 2 秒之后\nlist(); // [ 'oranges', 'apples' ]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面的代码,第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"1秒后","attrs":{}}],"attrs":{}},{"type":"text","text":" 被","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":",从执行的结果不难看出 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 跳过了第一个被","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":"的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" ,等待第二个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"2秒后","attrs":{}}],"attrs":{}},{"type":"text","text":" 执行完成的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.3 所有的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面来看下当所有的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 会出现什么结果,如下代码:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function rejectTimeout(reason, delay) {\n return new Promise((r, reject) => setTimeout(() => reject(reason), delay));\n}\nconst promise = Promise.any([\n rejectTimeout(new Error(\"fruits is empty\"), 1000),\n rejectTimeout(new Error(\"vegetables is empty\"), 2000),\n]);\n\n// 等待...\nconst list = async () => {\n try {\n const result = await promise;\n console.log(result);\n } catch (aggregateError) {\n console.log(aggregateError);\n console.log(aggregateError.errors);\n }\n};\n\nlist(); // [AggregateError: All promises were rejected]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从上面代码的执行结果来看,当所有输入","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 后, ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any([...])","attrs":{}}],"attrs":{}},{"type":"text","text":" 将返回一种特殊的错误 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AggregateError","attrs":{}}],"attrs":{}},{"type":"text","text":" 而被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,而详细的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 原因在属性 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"aggregateError.errors","attrs":{}}],"attrs":{}},{"type":"text","text":" 中 。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"小结","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 可用于以竞争方式并行执行独立的异步操作,以获取任何第一个成功执行完成的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的值。如果 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 的所有输入 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 都被","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 后,那么辅助函数返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 也会以错误集合的方式拒绝,该错误在一个特殊属性 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AggregateError","attrs":{}}],"attrs":{}},{"type":"text","text":" 中包含输入 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的拒绝原因:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"aggregateError.errors","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Promise.all()","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"方法 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.all(promises)","attrs":{}}],"attrs":{}},{"type":"text","text":" ,能够一次并行处理多个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":",并且只返回一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 实例, 那个输入的所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 回调的结果是一个数组。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面来看看 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":" 是如何工作的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.工作原理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":" 是一个内置的辅助函数,接受一组 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":"(或者一个可迭代的对象),并返回一个","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const allPromise = Promise.all([promise1, promise2, ...]);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"then","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法提取第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的值:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"allPromise.then((values) => {\n values; // [valueOfPromise1, valueOfPromise2, ...]\n});\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"async/await","attrs":{}}],"attrs":{}},{"type":"text","text":" 语法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const values = await allPromise;\nconsole.log(values); // [valueOfPromise1, valueOfPromise2, ...]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被解析或拒绝的方式。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 都被成功解析,那么 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 将使用一个包含各个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 已执行完成后的值的数组作为结果。数组中 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的顺序是很重要的——将按照这个顺序得到已实现的值。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/aa/aa1d1a00bc4b77d1bb2ac615b1056dd6.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是如果至少有一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,那么 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 会以同样的原因立即 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" (不等待其他 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的执行)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/21/2123d331caa31098b3c1d1c36984be2d.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果所有的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,等待所有的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 执行完成,但只会返回最先被","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"reject","attrs":{}}],"attrs":{}},{"type":"text","text":" 原因。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1e/1eb8def9599dfc9570247910cf0d2de7.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2. 使用指南","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"现在来深入介绍一下 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":", 在这之前,先来定义 2 个简单的函数。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"函数 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolveTimeout(value, delay)","attrs":{}}],"attrs":{}},{"type":"text","text":" 将返回一个在经过 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"delay","attrs":{}}],"attrs":{}},{"type":"text","text":" 时间后有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function resolveTimeout(value, delay) {\n return new Promise((resolve) => setTimeout(() => resolve(value), delay));\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"函数 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejectTimeout(reason, delay)","attrs":{}}],"attrs":{}},{"type":"text","text":" 将返回一个在经过 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"delay","attrs":{}}],"attrs":{}},{"type":"text","text":" 时间后有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"reject","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function rejectTimeout(reason, delay) {\n return new Promise((r, reject) => setTimeout(() => reject(reason), delay));\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下来使用上面定义的2个辅助函数来试试 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.1 完成所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面定义了一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" ,所有的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 都能够成功的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 值,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function resolveTimeout(value, delay) {\n return new Promise((resolve) => setTimeout(() => resolve(value), delay));\n}\nconst fruits = [\"potatoes\", \"tomatoes\"];\nconst vegetables = [\"oranges\", \"apples\"];\n\nconst allPromise = [\n resolveTimeout(fruits, 2000),\n resolveTimeout(vegetables, 1000),\n];\nconst promise = Promise.all(allPromise);\n\n// 等待... 2秒后\nconst list = async () => {\n try {\n const result = await promise;\n console.log(result);\n } catch (error) {\n console.log(error.errors);\n }\n};\n\nlist(); // [ [ 'potatoes', 'tomatoes' ], [ 'oranges', 'apples' ] ]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从上面执行的结果来看 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组是按照执行前 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的顺序组成其结果。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组的顺序直接影响结果的顺序,和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 执行完成的先后无关。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.2 一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"将上面数组 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 出现异常被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,如下代码:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const promise = Promise.all([\n rejectTimeout(new Error(\"fruits is empty\"), 5000),\n resolveTimeout(vegetables, 1000),\n]);\n\n// 等待...\nconst list = async () => {\n try {\n const result = await promise;\n console.log(result);\n } catch (error) {\n console.log(error);\n }\n};\n\nlist(); // Error: fruits is empty\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然而,在经过 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"5秒","attrs":{}}],"attrs":{}},{"type":"text","text":" 之后,第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 由于异常被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,使得 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 也被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,并返回跟第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 一样的错误信息:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Error: fruits is empty","attrs":{}}],"attrs":{}},{"type":"text","text":" ,即使在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"1秒","attrs":{}}],"attrs":{}},{"type":"text","text":" 后就完成的第二个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的值也不被采纳。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下来将数组 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 都抛出异常被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,通过定时器将 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 的顺序做个调整,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const promise = Promise.all([\n rejectTimeout(new Error(\"fruits is empty\"), 5000),\n rejectTimeout(new Error(\"vegetables is empty\"), 1000),\n]);\n\n// 等待...\nconst list = async () => {\n try {\n const result = await promise;\n console.log(result);\n } catch (error) {\n console.log(error);\n }\n};\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"经过 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"5秒","attrs":{}}],"attrs":{}},{"type":"text","text":" 之后完成执行,而结果显示为 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Error: vegetables is empty","attrs":{}}],"attrs":{}},{"type":"text","text":" ,不难看出 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"allPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 的原因是最先 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":" 的这种行为被称为快速失败,如果 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组中至少有一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,那么返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 也被拒绝。如果","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组中所有的都被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,那么返回的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被拒绝的原因是先","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":"的那一个。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"小结","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.all() ","attrs":{}}],"attrs":{}},{"type":"text","text":" 是并行执行异步操作并获取所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 值的最佳方法,非常适合需要同时获取异步操作结果来进行下一步运算的场合。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"方法 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled(promises)","attrs":{}}],"attrs":{}},{"type":"text","text":" ,返回一个在所有给定的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 都已经 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"fulfilled","attrs":{}}],"attrs":{}},{"type":"text","text":" 或 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 后的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" ,并带有一个对象数组,每个对象表示对应的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 结果。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面来看看 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 是如何工作的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.工作原理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 可用于并行执行独立的异步操作,并收集这些异步操作的结果。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"函数接受一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组(或通常是一个可迭代的)作为参数,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const statusesPromise = Promise.allSettled(promises);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"当所有输入 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 都被履行或拒绝时,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"statusesPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 会解析为一个具有其状态的数组:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"{ status: 'fulfilled', value:value }","attrs":{}}],"attrs":{}},{"type":"text","text":" : 如果相应的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 已经履行","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"{ status: 'rejected', reason: reason }","attrs":{}}],"attrs":{}},{"type":"text","text":" :如果相应的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被拒绝","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e1/e1e617bc84d6bb5e4f9e826ce3e59d2a.jpeg","alt":null,"title":"promise.allSettled","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"then","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法提取所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 的状态:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"statusesPromise.then((statuses) => {\n statuses; // [{ status: '...', value: '...' }, ...]\n});\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"async/await","attrs":{}}],"attrs":{}},{"type":"text","text":" 语法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const statuses = await statusesPromise;\n\nstatuses; // [{ status: '...', value: '...' }, ...]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的承诺总是以一系列状态实现,无论是否有一些(或者全部)输入承诺被拒绝。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.all()","attrs":{}}],"attrs":{}},{"type":"text","text":" 的最大不同:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 永远不会被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2. 使用指南","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"现在来深入介绍 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 的使用之前, 还是先来定义 2 个简单的函数。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function resolveTimeout(value, delay) {\n return new Promise((resolve) => setTimeout(() => resolve(value), delay));\n}\nfunction rejectTimeout(reason, delay) {\n return new Promise((r, reject) => setTimeout(() => reject(reason), delay));\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下来使用上面定义的2个辅助函数来试试 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.1 完成所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面定义了一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"statusesPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" ,所有的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 都能够成功的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 值,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const fruits = [\"potatoes\", \"tomatoes\"];\nconst vegetables = [\"oranges\", \"apples\"];\n\nconst statusesPromise = Promise.allSettled([\n resolveTimeout(fruits, 2000),\n resolveTimeout(vegetables, 1000),\n]);\n\n// 等待 2 秒 ...\nconst list = async () => {\n try {\n const statuses = await statusesPromise;\n console.log(statuses);\n } catch (error) {\n console.log(error);\n }\n};\n\nlist(); // [{ status: 'fulfilled', value: [ 'potatoes', 'tomatoes' ] },{ status: 'fulfilled', value: [ 'oranges', 'apples' ] }]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从上面执行的结果来看 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 状态数组是按照执行前 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"statusesPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的顺序组成其结果。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.2 一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"将上面第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 出现异常被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,如下代码:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const fruits = [\"potatoes\", \"tomatoes\"];\n\nconst statusesPromise = Promise.allSettled([\n resolveTimeout(fruits, 2000),\n rejectTimeout(new Error(\"Vegetables is empty\"), 1000),\n]);\n\n// 等待 2 秒 ...\nconst list = async () => {\n try {\n const statuses = await statusesPromise;\n console.log(statuses);\n } catch (error) {\n console.log(error);\n }\n};\n\nlist(); // // [{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] },{ status: 'rejected', reason: Error('Vegetables is empty') }]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"即使输入数组中的第二个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" , ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"statusesPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 仍然可以成功解析状态数组。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.3 所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"将上面所有的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 出现异常被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,如下代码:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const statusesPromise = Promise.allSettled([\n rejectTimeout(new Error(\"Fruits is empty\"), 2000),\n rejectTimeout(new Error(\"Vegetables is empty\"), 1000),\n]);\n\n// 等待 2 秒 ...\nconst list = async () => {\n try {\n const statuses = await statusesPromise;\n console.log(statuses);\n } catch (error) {\n console.log(error);\n }\n};\n\nlist(); // // [{ status: 'rejected', reason: Error('Fruits is empty') },{ status: 'rejected', reason: Error('Vegetables is empty') }]\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"小结","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"当需要执行并行和独立的异步操作并收集所有结果时,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled()","attrs":{}}],"attrs":{}},{"type":"text","text":" 就是不错的选择,即使一些异步操作可能失败。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Promise.race()","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"方法 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race(promises)","attrs":{}}],"attrs":{}},{"type":"text","text":" ,顾名思义就是赛跑的意思,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race([p1, p2, p3])","attrs":{}}],"attrs":{}},{"type":"text","text":" 里面 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组那个执行完成得快就获取那个的结果,不管结果本身是成功履行状态还是失败拒绝状态,只输出最快的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面来看看 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 是如何工作的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.工作原理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":",一旦迭代器中的某个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 履行或拒绝,返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 就会履行或拒绝。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"函数接受一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组(或通常是一个可迭代的)作为参数,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const racePromise = Promise.race(promises);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"当所有输入 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 中有一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 快速被履行或拒绝时,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"racePromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 就会解析快速完成的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 结果(履行或拒绝):","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/0a/0a1efa2ea5f702665a17e8991e7dca39.jpeg","alt":null,"title":"Promise.race()","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f7/f74b839f30e55004e5c40cb8bf24fe8b.jpeg","alt":null,"title":"Promise.race()","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"then","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法提取 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"racePromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的结果:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"racePromise.then((fastValue) => {\n fastValue // 快速完成的 promise\n});\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"async/await","attrs":{}}],"attrs":{}},{"type":"text","text":" 语法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const fastPromise = await racePromise;\n\nfastPromise; // 快速完成的 promise\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的承诺和最先完成的承诺信息一致。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 的不同:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 承诺列表中寻找第一个履行或拒绝的承诺;","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 是从承诺列表中查找第一个履行的承诺。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2. 使用指南","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"现在来深入介绍 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 的使用之前,同样先来定义 2 个简单的函数。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"function resolveTimeout(value, delay) {\n return new Promise((resolve) => setTimeout(() => resolve(value), delay));\n}\nfunction rejectTimeout(reason, delay) {\n return new Promise((r, reject) => setTimeout(() => reject(reason), delay));\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下来使用上面定义的2个辅助函数来试试 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.1 完成所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面定义了一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 数组 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"racePromise","attrs":{}}],"attrs":{}},{"type":"text","text":" ,所有的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 都能够成功的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 值,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const fruits = [\"potatoes\", \"tomatoes\"];\nconst vegetables = [\"oranges\", \"apples\"];\n\nconst racePromise = Promise.race([\n resolveTimeout(fruits, 5000),\n resolveTimeout(vegetables, 1000),\n]);\n\n// 等待 1 秒 ...\nconst list = async () => {\n try {\n const fastPromise = await racePromise;\n console.log(fastPromise);\n } catch (error) {\n console.log(error);\n }\n};\n\nlist(); // [ 'oranges', 'apples' ]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从上面执行的结果来看 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回最快履行的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 结果。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.2 一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"将上面第一个 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 出现异常被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,如下代码:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const fruits = [\"potatoes\", \"tomatoes\"];\n\nconst racePromise = Promise.race([\n resolveTimeout(fruits, 2000),\n rejectTimeout(new Error(\"Vegetables is empty\"), 1000),\n]);\n\n// 等待 1 秒 ...\nconst list = async () => {\n try {\n const fastPromise = await racePromise;\n console.log(fastPromise);\n } catch (error) {\n console.log(error);\n }\n};\n\nlist(); // Error: Vegetables is empty\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从上面的结果看,最先完成的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,那么 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"fastPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 也是被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面将","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" 的承诺时间延长到 5秒,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const fruits = [\"potatoes\", \"tomatoes\"];\n\nconst racePromise = Promise.race([\n resolveTimeout(fruits, 2000),\n rejectTimeout(new Error(\"Vegetables is empty\"), 5000),\n]);\n\n// 等待 2 秒 ...\nconst list = async () => {\n try {\n const fastPromise = await racePromise;\n console.log(fastPromise);\n } catch (error) {\n console.log(error);\n }\n};\n\nlist(); // [ 'potatoes', 'tomatoes' ]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从上面执行结果看到,最快完成的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 履行了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" ,那么 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"fastPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 也是履行了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"resolve","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.3 所有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"将上面所有的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 出现异常被 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"rejected","attrs":{}}],"attrs":{}},{"type":"text","text":" ,如下代码:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"const racePromise = Promise.race([\n rejectTimeout(new Error(\"Fruits is empty\"), 2000),\n rejectTimeout(new Error(\"Vegetables is empty\"), 1000),\n]);\n\n// 等待 1 秒 ...\nconst list = async () => {\n try {\n const fastPromise = await racePromise;\n console.log(fastPromise);\n } catch (error) {\n console.log(error);\n }\n};\n\nlist(); // Error: Vegetables is empty\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从结果来看,虽然两个承诺都被拒绝了,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"fastPromise","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 是最快被拒绝的 。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3. 使用场景","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"3.1. 性能测试","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在有异步操作的项目中,在对于网络或数据库请求进行性能进行优化的时候,可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promises","attrs":{}}],"attrs":{}},{"type":"text","text":" 来测试其优化效果,通过使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 来测试两种不同的方法的响应速度。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"3.2 最佳选择","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"例如获取同一类型的数据有多个请求服务器,同时向多个服务器发送请求,只要其中一个完成工作,就将其数据呈现,达到选择最佳线路的效果。这是可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 同时执行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 并在第一个成功后立即完成。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"小结","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise.race()","attrs":{}}],"attrs":{}},{"type":"text","text":" 为第一个已解决和已拒绝的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 执行回调函数,而 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise.any()","attrs":{}}],"attrs":{}},{"type":"text","text":" 为第一个已履行的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 执行回调函数,如果没有履行的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 则拒绝一个特殊属性 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AggregateError","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/63/6392ca89e6ca480694572b387d9a149c.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章