首頁 >web前端 >js教程 >掌握非同步 JavaScript:回呼、Promise 和簡化的 Async/Await

掌握非同步 JavaScript:回呼、Promise 和簡化的 Async/Await

Patricia Arquette
Patricia Arquette原創
2024-11-25 08:19:11913瀏覽

Mastering Asynchronous JavaScript: Callbacks, Promises, and Async/Await Simplified

非同步 JavaScript:從回呼到 Promise 和 Async/Await

介紹

JavaScript 是一種強大的單執行緒程式語言,廣泛用於 Web 開發。 JavaScript 中常見的挑戰是處理非同步任務,例如從 API 取得資料或執行時間敏感的操作,而不阻塞主執行緒。隨著時間的推移,開發人員已經從使用回調轉向使用 Promise,現在使用更優雅的 async/await 語法來管理非同步操作。本指南將引導您逐步了解這些概念,從基礎知識開始直到進階場景。到最後,您將能夠在現實應用程式中自信地使用非同步 JavaScript。


什麼是非同步程式設計?

在 JavaScript 中,從伺服器取得資料、讀取檔案或設定逾時等任務可能需要時間才能完成。 JavaScript 允許這些任務非同步運行,而不是等待這些任務完成(這會阻止程式其餘部分的執行)。這意味著它們的處理獨立於主程式流程,允許其他程式碼立即執行。


了解回調:起點

什麼是回調?

回呼是作為參數傳遞給另一個函數的函數。當第一個函數完成其操作時,它會執行回調函數以表示完成。

回調範例:了解基礎知識

function fetchData(callback) {
    setTimeout(() => {
        console.log("Data fetched!");
        callback();
    }, 2000); // Simulates a 2-second delay
}

function processData() {
    console.log("Processing data...");
}

fetchData(processData);

說明

  1. fetchData 模擬延遲取得資料。
  2. 延時後,執行回呼函數(processData),表示資料準備好了。

回調地獄:問題所在

使用巢狀回呼處理多個非同步任務很快就會導致程式碼不可讀且難以維護。

setTimeout(() => {
    console.log("Step 1: Data fetched");
    setTimeout(() => {
        console.log("Step 2: Data processed");
        setTimeout(() => {
            console.log("Step 3: Data saved");
        }, 1000);
    }, 1000);
}, 1000);

這個「厄運金字塔」使得調試和維護程式碼變得困難。


承諾:更好的選擇

什麼是承諾?

promise 是一個對象,表示現在、將來或永遠無法使用的值。 Promise 有三種狀態:

  • 待處理:初始狀態,既不滿足也不拒絕。
  • 已完成:操作成功完成。
  • 已拒絕:操作失敗。

Promise 例:重寫回調地獄

function fetchData(callback) {
    setTimeout(() => {
        console.log("Data fetched!");
        callback();
    }, 2000); // Simulates a 2-second delay
}

function processData() {
    console.log("Processing data...");
}

fetchData(processData);

Promise 的好處

  1. 透過連結提高了可讀性。
  2. 使用 .catch() 進行內建錯誤處理。
  3. 避免深層嵌套的回呼。

非同步/等待:現代優雅

什麼是異步/等待?

async/await 是承諾的語法糖,在 ES2017 中引入。它使非同步程式碼看起來是同步的,提高了可讀性和可維護性。

Async/Await 範例:簡化 Promise

setTimeout(() => {
    console.log("Step 1: Data fetched");
    setTimeout(() => {
        console.log("Step 2: Data processed");
        setTimeout(() => {
            console.log("Step 3: Data saved");
        }, 1000);
    }, 1000);
}, 1000);

它是如何運作的

  1. async 關鍵字:將函數宣告為非同步。
  2. await 關鍵字:暫停函數執行,直到 Promise 解決或拒絕。

非同步/等待的好處

  1. 順序、可讀的程式碼。
  2. 使用 try...catch 進行錯誤處理。
  3. 降低迴調複雜性。

使用 Async/Await 處理現實場景

並行執行:Promise.all

當需要並行執行多個獨立的非同步任務時:

function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("Data fetched!");
            resolve("Fetched data");
        }, 1000);
    });
}

function processData(data) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`Processing: ${data}`);
            resolve("Processed data");
        }, 1000);
    });
}

function saveData(data) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`Saving: ${data}`);
            resolve("Data saved");
        }, 1000);
    });
}

// Chaining Promises
fetchData()
    .then((data) => processData(data))
    .then((processedData) => saveData(processedData))
    .then((finalResult) => console.log(finalResult))
    .catch((error) => console.error("Error:", error));

錯誤處理:try...catch 與 .catch()

使用非同步函數的 try...catch 正確管理錯誤:

async function handleData() {
    try {
        const fetchedData = await fetchData();
        const processedData = await processData(fetchedData);
        const savedData = await saveData(processedData);
        console.log(savedData);
    } catch (error) {
        console.error("Error:", error);
    }
}

handleData();

有關異步 JavaScript 的常見常見問題解答

如果我忘記等待會發生什麼事?

函數傳回一個承諾而不是解析值。這可能會導致意外行為。

async function fetchAllData() {
    const task1 = fetchData();
    const task2 = fetchData();
    const results = await Promise.all([task1, task2]);
    console.log("All data fetched:", results);
}
fetchAllData();

我可以在沒有 Promise 的情況下使用 Async/Await 嗎?

不,await 只能與 Promise 一起使用。然而,像 fetch 和 Node.js 的 fs.promises API 這樣的函式庫提供了基於原生 Promise 的方法。

我什麼時候應該使用回調?

回呼對於小型、簡單的任務或使用不支援 Promise 的舊 API 時仍然有用。


結論

掌握非同步 JavaScript 對於任何使用現代 Web 應用程式的開發人員來說都是至關重要的。從回調開始,您可以了解 Promise 和 async/await 如何簡化非同步程式碼並提高可讀性。謹慎使用回調,利用 Promise 實現更好的錯誤處理,並擁抱 async/await 以獲得乾淨、直觀的程式碼。有了這些工具,您就可以準備好應對專案中的任何非同步挑戰。

以上是掌握非同步 JavaScript:回呼、Promise 和簡化的 Async/Await的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn