Syntax
Hai từ khóa async và await xuất hiện ở ES8 giúp xử lý các tác vụ bất đồng bộ tốt hơn. Đồng thời, chúng cũng giúp đoạn code trông dễ đọc và dễ hiểu hơn so với code được viết bằng promise thuần.
Tuy nhiên, async và await vẫn hoạt động xoay quanh các promise.
Async
Từ khóa async đứng trước một function khiến cho function đó trả về một promise. Trong đoạn code dưới, hàm square sẽ trả về một promise thay vì trả về giá trị.
async function square(n) {
return n * n
}Đoạn code trên tương đương với:
async function square(n) {
return Promise.resolve(n * n)
}Khi xuất giá trị trả về của square, ta sẽ nhận được kết quả như sau:
console.log(square(2)) // Promise {<fulfilled>: 4}Await
Xét ví dụ sau:
function squareOf(n) {
return n * n
}
function cubeOf(n) {
let square = 0
setTimeout(() => {
square = squareOf(n)
}, 3000)
console.log(square * n) // 0
}
cubeOf(3)Tác vụ square = squareOf(n) là một tác vụ bất đồng bộ, sẽ được thực hiện sau 3 giây. Do đó, square sẽ mang giá trị là 0 lúc truyền vào console.log().
Để khiến cho tác vụ console.log(square * n) chờ tác vụ square = squareOf(n), ta cần sử dụng từ khóa await như sau:
async function cubeOf(n) {
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve(squareOf(n))
}, 3000)
})
let square = await promise // <-- blocking here
console.log(square * n)
}Vì await chỉ được dùng cho một promise, ta cần tạo ra một promise và đem tất cả các tác vụ bất đồng bộ vào đó. Đồng thời, await chỉ có thể được sử dụng bên trong một hàm async, ta cần phải thêm từ khóa async vào trước hàm.
Từ khóa await ở đoạn code trên có hai chức năng:
- Thứ nhất,
awaitkhiến cho tác vụconsole.log(square * n)đến sau sẽ phải chờ cho promise hoàn thành công việc của nó. - Thứ hai,
awaittrích xuất kết quả trả về và gán cho biếnsquare.
Trong trường hợp tác vụ bất đồng bộ xảy ra lỗi, ta cần dùng hai từ khóa try và catch để xử lý lỗi:
async function cubeOf(n) {
try {
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve(squareOf(n))
}, 3000)
})
let square = await promise
console.log(square * n)
} catch (e) {
console.log(e)
}
}Ngoài ra, ta cũng có thể dùng thêm từ khóa finally sau khối lệnh của từ khóa catch.
Using async/await with Fetch API
Lấy dữ liệu từ API bằng hàm Fetch API và xử lý bằng async/await:
const url = "https://nekos.best/api/v2/neko"
async function fetchData() {
try {
const response = await fetch(url) // <-- wait for a promise
const data = await response.json() // <-- wait for a promise
return data
} catch (err) {
console.error(err)
}
}
async function displayData() {
const data = await fetchData() // <-- wait for a promise
console.log(data)
}
displayData()