1
一切的起點:正常的 Promise
在深入之前,我們先複習一下 Promise 是什麼。想像它是一個「承諾」,保證在未來某個時間點會給你一個結果,可能是「成功」或「失敗」。
const myPromise = new Promise((resolve, reject) => {
// 這裡執行一些需要時間的工作,例如跟伺服器要資料
// ... 工作完成後 ...
// 如果成功,就呼叫 resolve()
// 如果失敗,就呼叫 reject()
});
下面我們來模擬一下。點擊按鈕,看看這個 Promise 的狀態如何變化:
狀態: ⏳ 等待中 (Pending)
2
一個奇特的 Promise:() => {}
現在,來看我們今天的主角。如果我們給 `new Promise` 一個空的函式會發生什麼事?
const endlessPromise = new Promise(() => {});
// 這個函式裡面...
// - 沒有呼叫 resolve()
// - 沒有呼叫 reject()
// - 什麼事都沒做!
這個 Promise 就像一個說了「我保證」卻從不給出結果的朋友。它既不說成功,也不說失敗。因此,它會永遠處於「等待中」(Pending) 的狀態。點擊下方按鈕來建立它,你會發現它的狀態永遠不會改變。
狀態: ⏳ 等待中 (Pending)
3
終極應用:React Suspense 的魔法
React Suspense 是一個聰明的機制。當一個元件在渲染時需要等待非同步資料,它可以「暫停」渲染,並顯示一個備用的載入畫面 (Fallback UI)。
它的工作原理是:如果一個元件在渲染過程中「丟出 (throw)」一個 Promise,Suspense 就會捕捉到它,然後等待這個 Promise 完成。
function MyComponent() {
const data = useData(); // 假設這個 Hook 在資料未準備好時...
return <div>{data}</div>;
}
function useData() {
if (!dataIsReady) {
// ...就丟出一個 Promise 來「暫停」渲染!
throw new Promise(resolve => { /* ...去載入資料... */ });
}
return data;
}
// React 會像這樣處理
<Suspense fallback={<LoadingSpinner />}>
<MyComponent />
</Suspense>
現在,讓我們來看看當我們丟出「永遠等待的 Promise」時會發生什麼事:
React Suspense 模擬器
點擊下方按鈕開始渲染元件
🎉
總結
`throw new Promise(() => {});` 這行程式碼的威力在於:
- 它建立了一個永遠不會結束的 Promise。
- 當在 React 元件中丟出 (throw) 這個 Promise 時...
- React Suspense 會捕捉到它,並忠實地永遠顯示 Fallback 載入畫面。
這是一種強大的技巧,可以用於某些特殊場景,例如在 Storybook 中展示元件的載入狀態,或者在特定情況下故意讓一部分 UI 保持在載入中。現在,您已經完全掌握這個概念了!