Async và await
Thuộc phần Kiến thức cơ bản về Node.js trong hành trình Node.js của Coddy. Bài học 23 trên 33.
Một chuỗi lời gọi .then diễn đạt các bước khác với cách bạn hình dung: đọc, rồi phân tích, rồi lưu.
Bên trong một hàm async, await tạm dừng cho đến khi một promise hoàn tất và trả về giá trị của nó. Nếu promise thất bại, lỗi sẽ được ném tại đó, vì vậy try và catch sẽ xử lý lỗi. Trong một module, bạn cũng có thể dùng await ở cấp cao nhất.
import { readFile } from 'node:fs/promises';
const loadConfig = async () => {
try {
return JSON.parse(await readFile('config.json', 'utf8'));
} catch {
return {};
}
};
const config = await loadConfig();
console.log(config.port ?? 3000);Hàm async luôn trả về một promise, vì vậy bên gọi hàm cũng phải chờ nó bằng await. Nếu quên await, bạn sẽ nhận được chính promise đó, Promise { <pending> }, thay vì giá trị của nó.
Thử thách
DễBước này mở dự án công cụ dòng lệnh ghi chú đã chuẩn bị sẵn của khóa học, chứ không phải các tệp dự án của bạn trong Promises (bao gồm cả count.js). Phần bạn làm trước đó vẫn nằm trong bài học riêng. Hãy đọc các tệp được cung cấp trước khi chỉnh sửa store.js. Bản sao này có trình đọc ghi chú dùng promise và phần xử lý lỗi.
store.js hiện dùng các phiên bản promise của readFile và writeFile, còn các phương thức của nó là async. Nhưng chưa có gì chờ các promise hoàn tất, nên mọi lệnh đều lỗi. Hãy thêm await ở những nơi cần đợi một promise hoàn tất trước bước tiếp theo.
- Trong
store.js, ởload, hãy đợireadFilehoàn tất trước khiJSON.parsedùng văn bản. - Trong
store.js,loadlàasync, nên nó trả về một promise. Hãy đợi promise đó ở chỗ kho lưu trữ gán giá trị chonotes. Một module có thể dùngawaitở cấp cao nhất, bên ngoài mọi hàm. - Trong
store.js, hãy đợiwriteFiletrongsave, và đợithis.save()trongaddvàremove. - Trong
notes.js,store.addvàstore.removehiện làasync. Hãy đợi chúng trong các nhánhaddvàdone, đểnvàremovedchứa giá trị chứ không phải promise.
Tổng cộng cần bảy await. Sau đó, mọi lệnh sẽ hoạt động như trước. list hiển thị các ghi chú trong notes.json. Với hai ghi chú ban đầu, add Buy bread in ra Saved note 3., rồi done 1 in ra Done: Buy milk.
Thử nhé: nhập list vào ô sau $ node notes.js trước khi thay đổi gì. Bạn sẽ thấy notes.json is damaged: ..., nhưng tệp vẫn ổn: JSON.parse nhận một promise thay vì văn bản trong tệp. Sau khi chỉnh sửa, list sẽ hiển thị lại các ghi chú. Tiếp theo, nhập add Buy bread và xem Saved note 3.. Nhập done 1 và xem Done: Buy milk.
Tự làm thử
import { existsSync } from 'node:fs';
import { readFile, writeFile } from 'node:fs/promises';
const file = 'notes.json';
// readFile và writeFile giờ trả về promise. Dùng await để chờ từng promise.
const load = async () => {
if (!existsSync(file)) {
return [];
}
try {
return JSON.parse(readFile(file, 'utf8'));
} catch (err) {
console.error(`notes.json is damaged: ${err.message}`);
process.exit(1);
}
};
const store = {
notes: load(),
async save() {
writeFile(file, JSON.stringify(this.notes, null, 2));
},
async add(text) {
this.notes.push(text);
this.save();
return this.notes.length;
},
async remove(n) {
const [text] = this.notes.splice(n - 1, 1);
this.save();
return text;
},
};
export default store;
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Kiến thức cơ bản về Node.js
1Chạy JavaScript trên Node
Xin chào, NodeĐọc lệnhĐối số dòng lệnhCác lệnhTự luyện tập: Playground Express