在現代 JavaScript 與 Next.js 全端開發中,Promise 是處理非同步作業(如:API 請求、讀寫資料庫、計時器)的基石。這份筆記將帶你從零開始,完整掌握 Promise 的觀念、語法與實戰應用。
想像你去速食店點餐:
回到 JavaScript,要想理解 Promise,就需要先理解 JS 的執行環境:「單執行緒(Single-threaded)」
JavaScript 引擎在同一個時間點只能做一件事情。
如果今天去發送一個網路請求(API 呼叫)需要花費 3 秒鐘,按照傳統同步程式碼的邏輯,整個網頁的畫面會直接「卡死(Blocking)」3 秒鐘,使用者會無法點擊按鈕或滾動頁面。
為了不讓網頁卡死,JavaScript 需要一種機制:「我先送出請求,不擋住後面的程式碼,等資料回來後,你再通知我來拿。」
這個機制就是非同步(Asynchronous),而 Promise 就是這個非同步機制的「資料結構化具現化」。
一個 Promise 物件必然處於以下三種狀態之一:
resolve)。reject)。Promise 的狀態一旦從 Pending 轉變成 Fulfilled 或 Rejected 之後,就 定格 Settled 了,無法再變更。
我們可以透過 new Promise 建構子來建立一個 Promise 物件。它會接收一個執行函式(Executor Function),該函式帶有兩個參數:resolve(成功時呼叫)與 reject(失敗時呼叫)。
const checkInventory = (item) => {
return new Promise((resolve, reject) => {
// 模擬非同步操作(例如:查詢資料庫)
setTimeout(() => {
const stock = { apple: 5, banana: 0 };
if (stock[item] > 0) {
resolve(`成功!${item} 還有庫存:${stock[item]} 個`);
} else {
reject(new Error(`抱歉,${item} 已經賣完了!`));
}
}, 1000);
});
};
.then() 與 .catch()當我們拿到一個 Promise 實例後,可以用 .then() 接收成功結果,用 .catch() 捕捉錯誤:
checkInventory('apple')
.then((res) => {
console.log(res); // 1 秒後印出:"成功!apple 還有庫存:5 個"
})
.catch((err) => {
console.error(err.message);
})
.finally(() => {
console.log("查詢結束(無論成功與否都會執行)");
});
雖然 .then() 可以串接非同步任務,但當任務一多容易造成「回呼地獄(Callback Hell)」。在現代 JS/TS 與 Next.js 開發中,我們會使用 async/await 語法糖來讓非同步程式碼看起來像同步程式碼。
回呼地獄https://hyc.eshachem.com/program/js-callback-hell/
async function handleOrder() {
try {
// 透過 await 等待 Promise 完成
const result = await checkInventory('apple');
console.log(result);
} catch (error) {
// 等同於 .catch()
console.error("發生錯誤啦:", error.message);
} finally {
console.log("流程結束");
}
}
handleOrder();
現在很多工程師都會習慣直接用async / await,我一開始學習也是學async / await,但為了自己的目標想要成為更厲害的Next.js全端工程師,所以我決定開始來探討『為什麼』,第一個令我非常好奇的,就是這個async / await語法糖,也因此研究到Promise,就順便整理、寫了這篇文章~希望對你在前端、全端學習上有幫助!