iT邦幫忙

2025 iThome 鐵人賽

DAY 22
0
Modern Web

30天入門Java Script系列 第 22

Day22:Promise與async/await

  • 分享至 

  • xImage
  •  

在前端開發中,非同步處理是一個非常重要的概念
當程式需要等待資料,例如從伺服器抓資料、等待使用者輸入、計時器完成等等的時候,通常不希望整個頁面因此卡住,這個時候就會用到Promiseasync/await

1.同步與非同步的差別

由於JavaScript是單執行緒的語言,它一次只能做一件事,所以如果某段程式需要花時間(ex:讀資料/等待伺服器回應),那其他程式就得排隊等它做完,這會造成整個網頁的畫面卡住

為了解決這個問題,JavaScript採用了非同步執行的機制,讓我們可以先發出請求(例如抓API),然後等資料回來再執行下一步,這樣不會阻塞整個流程讓畫面卡住

2.回呼地獄(Callback Hell)

在早期,非同步操作通常用回呼函式(callback function)來處理
ex:

getData(function (result) {
  processData(result, function (processed) {
    saveData(processed, function () {
      console.log("全部完成!");
    });
  });
});

這樣的寫法雖然可行,但層層巢狀、難以閱讀與維護,俗稱回呼地獄

3.Promise

為了解決回呼地獄的問題,ES6引入了Promise
Promise的意思是當某個操作最終成功或失敗,並在完成後執行與結果相應的動作
Promise有三種狀態:
1.pending(進行中)
2.fulfilled(成功)
3.rejected(失敗)

範例:

const promise = new Promise((resolve, reject) => {
  const success = true;
  if (success) {
    resolve("資料載入成功!");
  } else {
    reject("載入失敗!");
  }
});

promise
  .then((message) => {
    console.log(message);
  })
  .catch((error) => {
    console.error(error);
  });

這樣寫的好處是,我們不用層層巢狀,只要呼叫.then().catch()

4.async/await

雖然Promise改善了可讀性,但.then()鏈仍然會讓程式變得冗長
於是ES8引入了async/await,讓非同步程式碼看起來幾乎像同步一樣簡潔

範例:

js
function getData() {
  return new Promise((resolve) => {
    setTimeout(() => resolve("資料載入完成"), 1000);
  });
}

async function showData() {
  console.log("開始載入...");
  const result = await getData(); // 等待Promise完成
  console.log(result);
  console.log("載入結束");
}

showData();

輸出順序會是:開始載入...>(1 秒後)>資料載入完成>載入結束

5.try…catch

在使用async/await時,也可以用try...catch來捕捉錯誤,會比.catch()更直覺
範例:

async function fetchData() {
  try {
    const response = await fetch("https://api.example.com/data");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("發生錯誤:", error);
  }
}

整理一下今天的內容:

概念 時代 特點
Callback 早期 容易陷入巢狀結構
Promise ES6 支援鏈式呼叫,提升可讀性
async/await ES8 可用同步風格撰寫非同步程式

上一篇
Day21:AJAX與Fetch API
下一篇
Day23:模組化
系列文
30天入門Java Script23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言