非同步編程可以讓我們在不阻塞主線程的情況下執行長時間的操作,比如讀取伺服器上的資料或處理計時器。Promise 是處理非同步操作的核心概念之一,它使得代碼更易讀且更具結構性。
JavaScript 是單線程語言,這意味著它一次只能執行一件事。非同步操作允許我們在不阻塞應用的情況下處理耗時任務,比如資料請求、定時任務或 I/O 操作。
setTimeout
、setInterval
)早期的 JavaScript 通常使用 Callback(回呼函數) 來處理非同步操作。回呼函數是當非同步操作完成時調用的函數,但過多的回呼可能會導致代碼難以維護,這種現象被稱為「回呼地獄」。
範例:
setTimeout(function() {
console.log("3 秒後執行此代碼");
}, 3000);
這種寫法在少量回呼的情況下可行,但一旦有多層嵌套,代碼就會變得混亂,難以維護。
為了解決回呼地獄的問題,ES6 引入了 Promise。Promise 是一種用來處理非同步操作的物件,它允許我們更好地控制非同步流程。
Promise 有三種狀態:
Promise 最終會解決為 fulfilled 或 rejected,並且可以使用 then
和 catch
方法來處理成功和失敗的結果。
你可以使用 new Promise()
來創建一個 Promise,並在 Promise 內部執行非同步操作。
範例:
let promise = new Promise(function(resolve, reject) {
let success = true;
if (success) {
resolve("操作成功!");
} else {
reject("操作失敗!");
}
});
promise.then(function(result) {
console.log(result); // 當操作成功時,輸出 "操作成功!"
}).catch(function(error) {
console.log(error); // 當操作失敗時,輸出 "操作失敗!"
});
在這裡,resolve
和 reject
是兩個回呼函數,分別用來通知 Promise 成功或失敗。根據不同的情況,我們可以在 then
中處理成功結果,或者在 catch
中捕獲錯誤。
then
方法用於在 Promise 完成時執行某些操作,catch
則是當 Promise 被拒絕時執行錯誤處理。
範例:
fetch("https://api.example.com/data")
.then(function(response) {
return response.json();
})
.then(function(data) {
console.log("資料獲取成功:", data);
})
.catch(function(error) {
console.log("資料獲取失敗:", error);
});
在這個例子中,fetch
是一個返回 Promise 的方法,我們使用 then
來處理成功結果,並使用 catch
來處理錯誤。
Promise.all
:當你有多個 Promise,需要等待所有 Promise 都完成時,可以使用 Promise.all
。它會返回一個新的 Promise,當所有的 Promise 都完成時,這個新的 Promise 也會完成。範例:
let promise1 = Promise.resolve(10);
let promise2 = Promise.resolve(20);
Promise.all([promise1, promise2]).then(function(results) {
console.log(results); // 輸出 [10, 20]
});
Promise.race
:它會返回第一個完成的 Promise,而不管是成功還是失敗。範例:
let slow = new Promise(resolve => setTimeout(resolve, 5000, "慢"));
let fast = new Promise(resolve => setTimeout(resolve, 1000, "快"));
Promise.race([slow, fast]).then(function(result) {
console.log(result); // 輸出 "快"
});
async
和 await
是基於 Promise 的語法糖,讓我們可以用同步的方式來寫非同步代碼,這使得代碼更清晰、更易於理解。
範例:
async function fetchData() {
try {
let response = await fetch("https://api.example.com/data");
let data = await response.json();
console.log("資料獲取成功:", data);
} catch (error) {
console.log("資料獲取失敗:", error);
}
}
fetchData();
在這個範例中,我們使用 await
來等待 fetch
完成,並通過 try/catch
來處理錯誤,這樣可以避免嵌套的 then/catch
,使代碼更為簡潔。