非同步處理指的是程式在等待某個操作完成時,可以繼續執行其他的程式碼,而不需要等待該操作完成後才繼續執行。這在處理需要花費長時間的網路請求或資料庫操作時非常重要,因為這樣可以保持使用者界面的反應靈敏,同時不影響其他的任務。
Promise 是 JavaScript 中用於處理非同步操作的物件,它代表了一個尚未完成、但在未來會完成的操作。Promise 有三種狀態:待定(pending)、實現(fulfilled)和拒絕(rejected)。當操作完成時,Promise 可以由待定轉為實現狀態,表示操作成功完成;或由待定轉為拒絕狀態,表示操作失敗。一旦 Promise 轉為實現或拒絕狀態,就不會再改變。
讓我們透過一個簡單的範例來理解 Promise 的運作方式:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = "這是從伺服器取得的資料";
// 模擬成功完成的操作
resolve(data);
// 模擬操作失敗的情況
// reject(new Error("無法取得資料"));
}, 2000);
});
}
fetchData()
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});
在這個範例中,我們定義了一個 fetchData
函式,它返回一個 Promise 物件。在該 Promise 的構造函式中,我們使用了 setTimeout
函式模擬一個耗時的操作。當操作完成後,我們呼叫 resolve
函式表示操作成功完成,並將取得的資料作為參數傳遞給 resolve
。如果操作失敗,我們可以呼叫 reject
函式並傳遞錯誤訊息作為參數。
接著,我們使用 .then
方法來設定當 Promise 轉為實現狀態時要執行的回調函式,並使用 .catch
方法來處理拒絕狀態的情況。在上述範例中,當 fetchData
的 Promise 成功實現時,我們將取得的資料輸出到控制台中;如果 Promise 被拒絕,則將錯誤訊息輸出到控制台中。
使用 Promise 的優點之一是可以透過 then
方法將多個非同步操作進行串聯。例如,我們可以進一步擴充上面的範例:
fetchData()
.then((data) => {
console.log(data);
return processData(data);
})
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
在這個擴充的範例中,我們在第一個 .then
方法中呼叫了 processData
函式,並將前一個操作獲得的資料作為參數傳遞給 processData
。當 processData
的 Promise 成功實現時,我們將結果輸出到控制台中。
除了使用 .then
和 .catch
方法之外,我們還可以使用 async/await
語法來更簡潔地處理 Promise。下面是一個使用 async/await
的例子:
async function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = "這是從伺服器取得的資料";
resolve(data);
}, 2000);
});
}
async function process() {
try {
const data = await fetchData();
console.log(data);
const result = await processData(data);
console.log(result);
} catch (error) {
console.error(error);
}
}
process();
在這個例子中,我們將 fetchData
函式和 process
函式標記為 async
,這樣它們就能夠使用 await
關鍵字來等待 Promise 的結果。透過 async/await
,我們可以使用同步的方式來撰寫非同步的程式碼,使得程式碼更易於閱讀和維護。
總結起來,JavaScript 中的非同步處理對於處理耗時的操作非常重要,以確保網頁的反應靈敏並提供良好的使用者體驗。Promise 是 JavaScript 提供的一個強大工具,它能夠輕鬆地管理和處理非同步操作,並透過串聯和 async/await
的方式使程式碼更具可讀性和可維護性。