Từ khóa async
được sử dụng để khai báo một hàm bất đồng bộ (asynchronous function). Một hàm được định nghĩa với từ khóa async
sẽ luôn trả về một Promise, và nó cho phép sử dụng cú pháp await
để xử lý các tác vụ bất đồng bộ một cách tuần tự, dễ đọc và rõ ràng hơn.
Đặc điểm của hàm async
:
- Trả về một Promise:
- Nếu trong hàm
async
có trả về một giá trị, giá trị đó sẽ được tự động bọc trong một Promise. - Nếu không trả về gì, hàm sẽ trả về
Promise<void>
.
- Nếu trong hàm
async function example() { return "Hello, async!"; } example().then((message) => console.log(message)); // "Hello, async!"
- Kết hợp với
await
:await
chỉ được sử dụng bên trong hàmasync
.- Nó sẽ tạm dừng việc thực thi của hàm
async
cho đến khi Promise được giải quyết (hoàn thành) và tiếp tục với kết quả của Promise.
async function fetchData() { console.log("Start fetching..."); const data = await new Promise((resolve) => setTimeout(() => resolve("Dữ liệu nhận được!"), 2000) ); console.log(data); console.log("Done fetching!"); } fetchData();
Start fetching... (Dừng trong 2 giây) Dữ liệu nhận được! Done fetching!
Các tình huống sử dụng async/await
:
1. Xử lý tác vụ bất đồng bộ một cách tuần tự:
Khi bạn cần thực thi nhiều tác vụ bất đồng bộ lần lượt, async/await
giúp tránh Promise chaining.
async function processTasks() { const task1 = await new Promise((resolve) => setTimeout(() => resolve("Task 1 hoàn thành!"), 1000)); console.log(task1); const task2 = await new Promise((resolve) => setTimeout(() => resolve("Task 2 hoàn thành!"), 2000)); console.log(task2); console.log("Tất cả tác vụ hoàn thành!"); } processTasks(); [code] Task 1 hoàn thành! (Dừng 1 giây) Task 2 hoàn thành! (Dừng 2 giây) Tất cả tác vụ hoàn thành!
2. Xử lý lỗi với try...catch
:
Bạn có thể dễ dàng quản lý lỗi khi sử dụng async/await
thông qua try...catch
.
async function fetchDataWithError() { try { const response = await new Promise((_, reject) => reject("Có lỗi xảy ra!")); console.log(response); } catch (error) { console.error("Lỗi:", error); } } fetchDataWithError();
Lỗi: Có lỗi xảy ra!
3. Chạy tác vụ song song với Promise.all()
:
Nếu không cần chờ tuần tự, bạn có thể chạy các tác vụ bất đồng bộ song song để tiết kiệm thời gian.
async function parallelTasks() { const [result1, result2] = await Promise.all([ new Promise((resolve) => setTimeout(() => resolve("Task A xong!"), 2000)), new Promise((resolve) => setTimeout(() => resolve("Task B xong!"), 1000)) ]); console.log(result1); // Task A xong! console.log(result2); // Task B xong! } parallelTasks();
Task B xong! Task A xong!
Lưu ý quan trọng:
await
chỉ dùng trong hàmasync
:- Nếu bạn sử dụng
await
bên ngoài một hàmasync
, nó sẽ gây lỗi.
Ví dụ:
// Sẽ gây lỗi! const data = await fetch('https://api.example.com');
- Nếu bạn sử dụng
- Chạy đồng thời thay vì tuần tự khi không cần thiết:
- Không sử dụng
await
tuần tự nếu các tác vụ không phụ thuộc lẫn nhau. Thay vào đó, sử dụngPromise.all()
.
- Không sử dụng
- Lỗi không được bắt (Unhandled Rejection):
- Đảm bảo bạn luôn xử lý lỗi từ Promise bằng
try...catch
hoặc.catch()
.
- Đảm bảo bạn luôn xử lý lỗi từ Promise bằng
Ưu điểm của async/await
:
- Cú pháp dễ đọc, giống mã đồng bộ, giúp giảm độ phức tạp.
- Dễ dàng xử lý lỗi với
try...catch
. - Loại bỏ vấn đề “callback hell”.
Nhược điểm:
- Mặc dù cú pháp dễ đọc, việc sử dụng
await
tuần tự có thể làm giảm hiệu suất nếu không cần thiết. - Người mới học dễ nhầm lẫn giữa bất đồng bộ và đồng bộ.

Dương Trần Hà, hiện mình đang là kỹ công nghệ phần mềm và cũng là giám đốc thành lập công ty DTH Solutions. Mình có nhiều năm kinh nghiệm, kiến thức chuyên môn lập trình, nodejs, nestjs, laravel, yii2, reactjs, nextjs. Mình đã phát triển rất nhiều dự án thực tế cho doanh nghiệp, cơ quan. Mình đã đạt được một số thành công nhỏ, đồng thời mình vẫn đang tiếp tục học tập để trau dồi kiến thức mỗi ngày. Mình rất yêu thích công nghệ, đam mê chia sẻ những kiến thức, thông tin hữu ích cho mọi người.