初學者指南:了解 JavaScript 中的 Promise 和 await

更新日期: 2024 年 9 月 14 日

在學習 JavaScript 處理非同步操作時,你可能會遇到兩個重要的概念:Promise 和 async/await。這篇文章將帶你深入了解這些概念,並展示如何在你的代碼中使用它們。

什麼是 Promise?

Promise 是用來處理非同步操作的一種 JavaScript 物件。它代表了一個尚未完成,但最終會完成(或失敗)的操作。

Promise 的三種狀態

  1. Pending(待定):初始狀態,操作尚未完成或失敗。
  2. Fulfilled(已完成):操作成功完成。
  3. Rejected(已拒絕):操作失敗。

如何創建和使用 Promise

你可以通過 new Promise 來創建一個 Promise,並使用 .then 和 .catch 方法來處理它的結果:

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true; // 模擬操作成功或失敗
    if (success) {
      resolve("操作成功!");
    } else {
      reject("操作失敗!");
    }
  }, 2000);
});

myPromise
  .then((message) => {
    console.log(message); // 打印 "操作成功!"
  })
  .catch((error) => {
    console.error(error); // 打印 "操作失敗!"
  });

若看不懂以上內容,請先閱讀此文:初學者指南:了解 JavaScript 的 Promise 物件

什麼是 async/await?

async/await 是在 ECMAScript 2017(ES8)中引入的語法糖,用於更方便地處理 Promise。

它使得非同步代碼看起來像同步代碼,從而提高了代碼的可讀性。

使用 async 定義非同步函數

async 關鍵字用來定義一個非同步函數。非同步函數總是返回一個 Promise:

async function myAsyncFunction() {
  return "Hello, async!";
}

myAsyncFunction().then((message) => {
  console.log(message); // 打印 "Hello, async!"
});

使用 await 等待 Promise

await 關鍵字用來等待一個 Promise 的結果。

它只能在 async 函數內使用:

async function myAsyncFunction() {
  const message = await myPromise; // 等待 myPromise 完成
  console.log(message); // 打印 "操作成功!"
}

myAsyncFunction();

這段代碼的作用與使用 .then 方法相同,但看起來更像同步代碼。

.then 方法與 async/await 差異

讓我們來對比一下使用 .then 方法和使用 async/await 的代碼,從而更好地理解這一點。

使用 .then 方法的代碼

首先,我們看看如何使用 .then 方法來處理 Promise:

// 定義一個模擬非同步操作的函數
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = true; // 模擬操作成功或失敗
      if (success) {
        resolve("數據獲取成功!");
      } else {
        reject("數據獲取失敗!");
      }
    }, 2000);
  });
}

// 使用 .then 和 .catch 方法來處理 Promise
fetchData()
  .then((data) => {
    console.log(data); // 打印 "數據獲取成功!"
    return data; // 可以選擇返回一些數據,繼續鏈式調用
  })
  .catch((error) => {
    console.error(error); // 打印 "數據獲取失敗!"
  });

使用 async/await 的代碼

接下來,我們看看如何使用 async/await 來處理同樣的 Promise:

// 定義一個模擬非同步操作的函數
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = true; // 模擬操作成功或失敗
      if (success) {
        resolve("數據獲取成功!");
      } else {
        reject("數據獲取失敗!");
      }
    }, 2000);
  });
}

// 使用 async/await 來處理 Promise
async function getData() {
  try {
    const data = await fetchData(); // 等待 fetchData 完成
    console.log(data); // 打印 "數據獲取成功!"
  } catch (error) {
    console.error(error); // 打印 "數據獲取失敗!"
  }
}

getData();

對比分析

  1. 結構化
  • .then 方法:使用 .then 方法會導致鏈式調用,當有多個非同步操作需要依次進行時,會產生多層嵌套。
  • async/await:使用 async/await 則使得代碼結構更像同步操作,線性化的代碼結構更直觀。
  1. 錯誤處理
  • .then 方法:錯誤處理需要在鏈的末端使用 .catch 方法,或者在每個 .then 內部進行處理。
  • async/await:使用 try/catch 块來處理錯誤,錯誤處理邏輯更加集中,代碼更易讀。
  1. 可讀性
  • .then 方法:當有多個 .then 需要處理時,代碼會變得不太好閱讀。
  • async/await:代碼更加簡潔,易於理解和維護。

更複雜的示例

假設我們有多個非同步操作需要依次進行,這是使用 .then 方法和 async/await 的對比:

使用 .then 方法:

function firstTask() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("完成任務1");
    }, 1000);
  });
}

function secondTask() {
  return new Promise((resolve,
 reject) => {
    setTimeout(() => {
      resolve("完成任務2");
    }, 1000);
  });
}

function thirdTask() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("完成任務3");
    }, 1000);
  });
}

firstTask()
  .then((message) => {
    console.log(message); // 打印 "完成任務1"
    return secondTask();
  })
  .then((message) => {
    console.log(message); // 打印 "完成任務2"
    return thirdTask();
  })
  .then((message) => {
    console.log(message); // 打印 "完成任務3"
  })
  .catch((error) => {
    console.error(error);
  });

使用 async/await

function firstTask() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("完成任務1");
    }, 1000);
  });
}

function secondTask() {
  return new Promise((resolve,
 reject) => {
    setTimeout(() => {
      resolve("完成任務2");
    }, 1000);
  });
}

function thirdTask() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("完成任務3");
    }, 1000);
  });
}

async function runTasks() {
  try {
    const firstMessage = await firstTask();
    console.log(firstMessage); // 打印 "完成任務1"

    const secondMessage = await secondTask();
    console.log(secondMessage); // 打印 "完成任務2"

    const thirdMessage = await thirdTask();
    console.log(thirdMessage); // 打印 "完成任務3"
  } catch (error) {
    console.error(error);
  }
}

runTasks();

結語

使用 async/await 可以讓你寫出更具可讀性和可維護性的代碼,特別是在處理多個非同步操作時。

希望這篇文章能幫助你更好地理解 async/await 與 .then 方法之間的對比,並能夠有效地在你的 JavaScript 項目中使用它們。

Similar Posts