JavaScript 非同步處理方式
JavaScript 提供了多種處理非同步操作的方式,包括 Callback、Promise 和 Async/Await。每種方式都有其特點和適用場景。
Callback Function
Callback Function(回調函數) 是 JavaScript 中處理非同步操作最傳統的方式。它是一個作為參數傳遞給另一個函數的函數,當特定事件發生或操作完成時會被調用。
基本概念:
-
什麼是 Callback:
- 一個函數作為參數傳遞給另一個函數
- 在特定條件滿足時被調用
- 常用於處理非同步操作
-
基本語法:
function doSomething(callback) {// 執行某些操作const result = "操作完成";callback(result); // 調用回調函數}doSomething(function (result) {console.log(result); // "操作完成"}); -
常見應用場景:
- 事件處理
- 定時器
- AJAX 請求
- 文件讀取
Callback 的優缺點:
優點:
- 簡單直觀
- 廣泛支援
- 不需要額外的語法
缺點:
- 容易產生「回調地獄」(Callback Hell)
- 錯誤處理困難
- 代碼可讀性差
回調地獄問題:
// 回調地獄示例
getData(function (a) {
getMoreData(a, function (b) {
getEvenMoreData(b, function (c) {
getFinalData(c, function (d) {
console.log(d);
});
});
});
});
Promise
Promise 本身是同步函數。在 JavaScript 中,當你創建一個 Promise 物件(例如使用 new Promise()),這是一個同步的操作。Promise 的構造函數會立即執行,並且傳入的執行器函數(executor function,即 (resolve, reject) => { ... })也會同步執行。
詳細說明:
-
Promise 構造函數是同步的: 當你執行
new Promise((resolve, reject) => { ... })時,執行器函數會立即運行,而不是等到事件循環的下一個 tick。這意味著執行器內的同步代碼會在當前調用棧中立即執行。console.log("開始");const promise = new Promise((resolve, reject) => {console.log("執行器內部");resolve("成功");});console.log("結束");輸出結果:
開始執行器內部結束可以看到,
執行器內部的日誌會在結束之前打印,證明執行器是同步運行的。 -
Promise 的狀態變化和回調是非同步的: 雖然
Promise的創建和執行器是同步的,但當resolve或reject被調用時,與之相關的.then()、.catch()或.finally()回調函數會被放入微任務隊列(microtask queue),並在當前調用棧清空後(即同步代碼執行完畢後)才會執行。這使得 Promise 的回調處理是非同步的。console.log("開始");const promise = new Promise((resolve, reject) => {console.log("執行器內部");resolve("成功");});promise.then((result) => {console.log("then 回調:", result);});console.log("結束");輸出結果:
開始執行器內部結束then 回調: 成功這裡可以看到,
.then的回調是在同步代碼(開始和結束)執行完後才執行的,這是因為.then的處理被推遲到微任務隊列。 -
總結:
Promise的創建和執行器函數是同步的。Promise的狀態變更(resolve或reject)觸發的回調(如.then、.catch)是非同步的,會在微任務隊列中執行。- 這種設計使得
Promise能夠在同步代碼中初始化,但其結果處理是非同步的,符合 JavaScript 的事件循環模型。