關於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}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章