Giải thích đơn giản: async/await vs Promise trong JavaScript

Promiseasync/await là hai cách tiếp cận để xử lý bất đồng bộ trong JS. Về bản chất, async/await chỉ là cú pháp “đường tắt” (syntactic sugar) của Promise, giúp code dễ đọc hơn. Dưới đây là so sánh, cách dùng đúng, bẫy thường gặp và các demo chạy trực tiếp trong trình duyệt.

Giải thích đơn giản: async/await vs Promise trong JavaScript

Promise là gì?

  • Một giá trị đại diện cho kết quả trong tương lai, có 3 trạng thái: pending, fulfilled, rejected.
  • Xử lý kết quả bằng .then(), lỗi bằng .catch(), dọn dẹp bằng .finally().
fetch('/api/user')
  .then(r => r.json())
  .then(data => console.log('User', data))
  .catch(err => console.error(err))
  .finally(() => console.log('done'));

async/await là gì?

  • Hàm khai báo async luôn trả về Promise.
  • await “tạm dừng” trong phạm vi hàm async cho đến khi Promise hoàn thành (không chặn event loop).
async function loadUser() {
  try {
    const r = await fetch('/api/user');
    const data = await r.json();
    console.log('User', data);
  } catch (err) {
    console.error(err);
  } finally {
    console.log('done');
  }
}

So sánh nhanh

Tiêu chí Promise async/await
Độ dễ đọc Dễ tạo “callback chain” dài Gần như code đồng bộ, dễ đọc
Xử lý lỗi .catch() cuối chuỗi try/catch theo block
Song song Dùng Promise.all thuận tiện Dùng Promise.all (đừng await trong vòng lặp)
API tổng hợp all, allSettled, race, any Vẫn dùng các API Promise
Tương thích Rộng rãi Hiện đại, đã hỗ trợ tốt (kể cả top‑level await trong môi trường hỗ trợ module)

Xử lý lỗi: .catch vs try/catch

// Promise
getUser().then(saveUser).catch(handleError);

// async/await
try {
  const u = await getUser();
  await saveUser(u);
} catch (e) {
  handleError(e);
}

Tuần tự vs Song song: tránh await trong vòng lặp

// (KHÔNG NÊN) tuần tự chậm
for (const url of urls) {
  const r = await fetch(url);       // đợi từng cái
  results.push(await r.json());
}

// (NÊN) song song nhanh hơn
const promises = urls.map(u => fetch(u).then(r => r.json()));
const results = await Promise.all(promises);

Các API Promise hữu ích

  • Promise.all([p1, p2]): thất bại nếu bất kỳ promise nào fail; nhanh cho tác vụ bắt buộc đủ.
  • Promise.allSettled([p1, p2]): luôn trả kết quả cho tất cả, hữu ích khi không muốn fail cả lô.
  • Promise.race([p1, p2]): trả kết quả/lỗi của promise hoàn thành đầu tiên.
  • Promise.any([p1, p2]): trả kết quả đầu tiên thành công; chỉ fail nếu tất cả đều fail.

Chuyển từ Promise chain sang async/await

// Promise chain
login()
  .then(getProfile)
  .then(render)
  .catch(showError);

// async/await
try {
  const session = await login();
  const profile = await getProfile(session);
  render(profile);
} catch (e) {
  showError(e);
}

Thực hành tốt

  • Tách khởi tạo promiseawait để chạy song song khi có thể.
  • Dùng try/catch ở ranh giới (controller/handler); để hàm dưới ném lỗi lên trên.
  • Với tác vụ độc lập: Promise.all hoặc allSettled.
  • Tránh mix lẫn .thenawait trong cùng một flow trừ khi thật cần thiết.
  • Top‑level await: dùng trong module ES (<script type="module">) hoặc bundler hiện đại.

Demo trực quan (chạy ngay tại đây)

Dùng các nút dưới đây để thấy khác biệt giữa Promise chain, async/await, tuần tự vs song song và cách bắt lỗi.


Kết luận

Nếu muốn dễ đọcđiều khiển luồng theo khối, hãy dùng async/await. Khi cần song song hoặc thao tác với nhiều promise một lúc, hãy tận dụng các API của Promise như all / allSettled. Nhớ rằng async/await không thay thế Promise — chúng bổ trợ cho nhau.

Bình luận


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...