TypeScript cơ bản – Promise, async/await và kiểm tra dữ liệu API
- 17-10-2026
- Toanngo92
- 0 Comments
Khi đọc dữ liệu từ server, ứng dụng không có kết quả ngay lập tức. Promise mô tả một tác vụ sẽ hoàn thành hoặc thất bại trong tương lai; async/await giúp viết phần sử dụng kết quả theo thứ tự dễ đọc. TypeScript bổ sung thông tin về kiểu kết quả, nhưng dữ liệu thật từ mạng vẫn cần được kiểm tra.
Mục lục
1. Kiểu trả về của hàm async
async function getTitle(): Promise<string> {
return "TypeScript cơ bản";
}
async function showTitle(): Promise<void> {
const title = await getTitle();
console.log(title.toUpperCase());
}
void showTitle();
GetTitle trả về Promise<string>, dù câu lệnh return viết một chuỗi. Sau await, title là string. Hàm async không tạo kết quả nghiệp vụ có thể khai báo Promise<void>. Await không chặn toàn bộ luồng giao diện trong lúc chờ mạng; nó tạm dừng phần tiếp theo của hàm async hiện tại.
2. Mô tả dữ liệu muốn sử dụng
interface PostSummary {
id: number;
title: string;
}
Ví dụ sử dụng JSONPlaceholder, một API minh họa công khai không cần gửi thông tin đăng nhập. API có thể trả thêm trường khác; ứng dụng này chỉ cần id và title. Định nghĩa interface không buộc server trả đúng hai trường đó và cũng không xóa các trường còn lại khỏi object.
3. Kiểm tra dữ liệu unknown
function isPostSummary(value: unknown): value is PostSummary {
return typeof value === "object" && value !== null &&
"id" in value && typeof value.id === "number" && Number.isFinite(value.id) &&
"title" in value && typeof value.title === "string";
}
Dữ liệu được giữ ở kiểu unknown cho đến khi có kiểm tra. Hàm trên xác nhận object khác null, id là số hữu hạn và title là chuỗi. Đây là yêu cầu tối thiểu của PostSummary; nếu ứng dụng cần id nguyên dương hoặc title không rỗng, phải bổ sung điều kiện nghiệp vụ. Dữ liệu lồng nhau cũng cần kiểm tra tương ứng.
4. Gọi fetch và kiểm tra HTTP
async function loadPost(url: string): Promise<PostSummary> {
const response = await fetch(url);
if (!response.ok) {
throw new Error("HTTP " + response.status);
}
const data: unknown = await response.json();
if (!isPostSummary(data)) {
throw new Error("Dữ liệu bài viết không đúng cấu trúc");
}
return data;
}
Fetch có thể thất bại do mạng; response.json() có thể thất bại vì nội dung không phải JSON. Với HTTP 404 hoặc 500, fetch thông thường vẫn tạo Response, vì vậy cần kiểm tra response.ok. Khi type guard trả true, data được thu hẹp thành PostSummary và có thể được trả lại từ hàm.
5. Sử dụng kết quả và xử lý lỗi
async function main(): Promise<void> {
try {
const post = await loadPost("https://jsonplaceholder.typicode.com/posts/1");
console.log(post.id, post.title);
} catch (error: unknown) {
console.error(
error instanceof Error ? error.message : "Có lỗi không xác định"
);
}
}
void main();
export {};
Ghép các khai báo PostSummary, isPostSummary, loadPost và main vào src/main.ts. Biên dịch theo bài cấu hình, rồi chạy bằng phiên bản Node.js có fetch tích hợp hoặc trên trình duyệt hiện đại. Ví dụ cần kết nối Internet và phụ thuộc việc API minh họa đang hoạt động. Trong catch, giá trị được ném có thể không phải Error, nên phải kiểm tra trước khi đọc message.
Void trước main diễn đạt rằng nơi gọi không dùng giá trị Promise; nó không tự bắt lỗi. Ở ví dụ này, lỗi của thao tác tải đã được xử lý trong main. Với một hàm khác chưa có try/catch, vẫn cần await hoặc .catch để xử lý Promise bị từ chối.
6. Không dùng ép kiểu thay cho xác thực
Viết const data = await response.json() as PostSummary không kiểm tra id hay title lúc chạy. Tương tự, một hàm getJson<T>() chỉ ép kết quả thành T cũng không chứng minh dữ liệu đúng. Với API thật, hãy dùng type guard hoặc công cụ xác thực phù hợp, đồng thời phân biệt rõ lỗi mạng, lỗi HTTP và lỗi cấu trúc dữ liệu.
Đọc thêm: MDN: Using the Fetch API.
Đọc thêm: TypeScript: Narrowing.
Đọc tiếp trong loạt bài
Bài trước: TypeScript cơ bản – DOM, sự kiện và biểu mẫu trên trình duyệt
Bài tiếp theo: TypeScript cơ bản – Class, constructor, phạm vi truy cập và implements

