Home >Web Front-end >JS Tutorial >Mastering Asynchronous JavaScript: A Guide to Promises and Async/Await

Mastering Asynchronous JavaScript: A Guide to Promises and Async/Await

Susan Sarandon
Susan SarandonOriginal
2024-10-06 14:21:03443browse

Mastering Asynchronous JavaScript: A Guide to Promises and Async/Await

JavaScript 的非同步特性對於現代 Web 開發來說既強大又必不可少。從從 API 取得資料到處理使用者輸入,非同步操作很常見,並且需要高效率的處理。 ECMAScript 6 (ES6) 中引入的Promises 和ECMAScript 2017 中的Async/Await 徹底改變了開發人員處理非同步程式碼的方式,使其更乾淨、更具可讀性。

在本部落格中,我們將探討 PromisesAsync/Await、它們的工作原理以及何時在 JavaScript 專案中使用它們。


了解非同步 JavaScript

JavaScript 是單執行緒的,這表示一次只能執行一個動作。然而,諸如網路請求、檔案讀取或計時器之類的非同步操作允許 JavaScript 處理原本會阻塞主執行緒的任務,使其對使用者操作的回應更加靈敏。

在Promises和Async/Await之前,非同步操作是使用回呼來處理的,這常常導致回調地獄  -  深度嵌套且難以維護的回調結構。


承諾:向前邁出一步

A Promise 是一個表示非同步操作最終完成(或失敗)的物件。與回調相比,它允許您以更結構化的方式處理非同步任務。 Promise 可以處於以下三種狀態之一:

  • 待處理:操作仍在進行中。
  • 已完成:操作已成功完成。
  • 已拒絕:操作失敗。

做出承諾

要建立一個 Promise,您需要傳入一個有兩個參數的函數:resolve 和reject。在 Promise 中,您執行非同步任務,並根據結果呼叫「resolve」(成功時)或「reject」(失敗時)。


const fetchData = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const data = { name: 'Ishan', age: 25 };
            resolve(data);
        }, 1000);
    });
};


在上面的範例中,fetchData 函數傳回一個承諾,該承諾將在 1 秒後解析所取得的資料。

消費承諾

您可以使用 .then() 來處理承諾的結果(如果成功),使用 .catch()(如果發生錯誤)。


fetchData()
    .then(data => {
        console.log(data); // { name: 'Ishan', age: 25 }
    })
    .catch(error => {
        console.error('Error:', error);
    });


  • .then(): 當 Promise 解決時執行。
  • .catch(): 當 Promise 被拒絕時執行。

連結承諾

Promise 最強大的功能之一是它們能夠連結多個非同步操作。一個 .then() 的結果可以傳遞給下一個。


fetchData()
    .then(data => {
        return data.name.toUpperCase(); // Modify data
    })
    .then(upperName => {
        console.log(upperName); // 'ISHAN'
    })
    .catch(error => {
        console.error('Error:', error);
    });


Promise 組合器

Promise 還具有內建的組合器方法,可以幫助同時處理多個非同步操作。

  • Promise.all(): 等待所有 Promise 解析並傳回其結果陣列。如果任何承諾被拒絕,則整個承諾都被拒絕。

Promise.all([fetchData(), fetchData()])
    .then(results => console.log(results))
    .catch(error => console.error(error));


  • Promise.race(): 傳回第一個要解決或拒絕的 Promise 的結果。

Promise.race([fetchData(), fetchData()])
    .then(result => console.log(result))
    .catch(error => console.error(error));



非同步/等待:Promise 的語法糖

雖然 Promise 有助於建立非同步程式碼,但在處理多個非同步操作時,連結 .then() 呼叫仍然會變得複雜。這就是 Async/Await 的用武之地。 async/await 在 ES2017 中引入,讓您可以編寫看起來同步的非同步程式碼。

使用非同步和等待

要使用 async/await,請將函數標記為 async,並在函數內,在 Promise 之前使用 wait 關鍵字。這使得 JavaScript 在繼續之前等待承諾解決(或拒絕)。


const fetchData = () => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve({ name: 'Ishan', age: 25 });
        }, 1000);
    });
};

const getData = async () => {
    const data = await fetchData();
    console.log(data); // { name: 'Ishan', age: 25 }
};

getData();


請注意,與連結 .then() 呼叫相比,此程式碼要簡潔得多。它讀起來像同步程式碼,但非同步工作。

使用 try 和 catch 進行錯誤處理

使用 async/await 時,可以使用 try/catch 處理錯誤,這比使用具有 Promise 的 .catch() 更容易管理錯誤。


const getData = async () => {
    try {
        const data = await fetchData();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    }
};

getData();


這種方法使錯誤處理更加可預測,並將所有邏輯保留在一個程式碼區塊中。


何時使用 Promise 與 Async/Await

Promise 和 async/await 都實現了處理非同步操作的相同目標。那麼,什麼時候應該使用其中一種而不是另一種呢?

以下情況使用 Promise

  • 您需要使用 Promise 組合器,例如 Promise.all() 或 Promise.race()。
  • 您正在處理少量非同步操作,並且 .then() 連結仍然是可管理的。

在下列情況下使用非同步/等待

  • You want cleaner, more readable code.
  • You have multiple asynchronous operations that rely on each other's results.
  • Error handling needs to be centralized and easier to manage.

Mixing Async/Await with Promise Combinators

One of the advantages of async/await is that it can be combined with promise combinators like Promise.all() to handle multiple asynchronous operations simultaneously.


const fetchData1 = () => {
    return new Promise(resolve => setTimeout(() => resolve('Data 1'), 1000));
};

const fetchData2 = () => {
    return new Promise(resolve => setTimeout(() => resolve('Data 2'), 2000));
};

const getAllData = async () => {
    try {
        const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
        console.log(data1, data2); // 'Data 1', 'Data 2'
    } catch (error) {
        console.error('Error:', error);
    }
};

getAllData();


This approach allows you to run promises in parallel while still benefiting from the simplicity of async/await.


Conclusion

Promises and Async/Await are essential tools for managing asynchronous code in JavaScript. While promises provide a structured way to handle async tasks, async/await takes it to the next level by offering a cleaner and more readable syntax. Both approaches have their place, and knowing when to use them will make you a more efficient and effective JavaScript developer.

If you're new to asynchronous JavaScript, start with promises and experiment with async/await to see how they can transform the way you write code.

The above is the detailed content of Mastering Asynchronous JavaScript: A Guide to Promises and Async/Await. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn