## Promise.race 實作 `Promise.race` 是 JavaScript 提供的一個方法,用於競賽多個 Promise,並返回第一個完成(無論是解決還是拒絕)的 Promise 的結果。這意味著,無論哪個 Promise 最先完成,`Promise.race` 都會使用該 Promise 的結果來解決或拒絕它返回的新 Promise。 Promise.race 的實現原理也和事件循環(Event Loop)的工作機制緊密相關。以下是運作過程及其在事件循環中的各個階段。 ### Promise.race 的實現原理 1. 創建外層 Promise: * Promise.race 返回一個新的外層 Promise,這個 Promise 的狀態由傳入的 promiseArray 陣列中的任意一個 Promise 首先被解析(fulfilled)或拒絕(rejected)來決定。 1. 遍歷 promiseArray 陣列: * 逐個遍歷傳入的 Promise,並為每個 Promise 註冊 then 和 catch 處理器。 * 當任意一個 Promise 被觸發時,對應的處理器會被推入微任務佇列(Microtask Queue)。 1. 處理微任務: * 事件循環首先執行堆疊中的同步代碼,然後處理微任務佇列中的回調函式。 * 最早被觸發的 Promise 的回調函式最先被執行,外層 Promise 的狀態立即被決定。 1. 輸出結果: * 當最早的 Promise 解析或拒絕後,外層 Promise 在跟著一起對應結果或錯誤被返回。 * 隨後的 Promise 的狀態不再影響外層的結果。 poo-poo code ```javascript! const promiseArray = [ new Promise((resolve) => setTimeout(() => resolve('First'), 500)), new Promise((resolve) => setTimeout(() => resolve('Second'), 100)), new Promise((resolve) => setTimeout(() => resolve('Third'), 300)) ]; const race = (items) => { return new Promise((resolve, reject) => { items.forEach(item=> { item .then(res=> resolve(item)) .catch(e=> reject(e)) }) }) } console.log(await race(promiseArray)) ``` > 在這個例子中,最先被解析的 Promise 是第二個(100 毫秒後),因此返回的結果是 "Second"。事件循環確保最先被解析的 Promise 的回調函式最早被執行。 ### 事件循環的作用 * 堆疊(Call Stack): 同步代碼逐行執行,調用的函式壓入堆疊,執行完後彈出。 * 微任務佇列(Microtask Queue): 包含 Promise 的回調中,微任務在每個堆疊清空後立即執行,優先於宏任務。 * 宏任務佇列(Macrotask Queue): 包含 setTimeout 等回調。宏任務在所有微任務執行完後執行。 ### 總結 > 所以簡單來說其實 Promise.race 只是在 promiseArray 外再包了一層 promise,等誰是最快的回傳而已。 * Promise.race 返回最早被解析或拒絕的 Promise 的結果。 * 事件循環在處理微任務時優先於宏任務,保證了回調函式的執行順序。 * Promise.race 通過遍歷 promiseArray 陣列並註冊回調函式,實現了比賽機制,最先完成的 Promise 決定了比賽的結果。 * 通過理解 Promise.race 與事件循環的交互過程,我們能更好地掌握 JavaScript 中的非同步操作和回調機制。