Async/await trong TypeScript

Async/await trong TypeScript

Bài viết này giải thích về async/await trong TypeScript.

YouTube Video

Async/await trong TypeScript

Async trong TypeScript là một từ khóa dùng để mô tả ngắn gọn các hoạt động bất đồng bộ và hoạt động tương tự như cú pháp async/await trong JavaScript. Các hàm async được thiết kế để làm cho việc xử lý các hàm trả về Promises trở nên trực quan hơn.

Cơ bản về các hàm async

Các hàm được khai báo với từ khóa async luôn trả về một Promise. Dưới đây là một ví dụ cơ bản:.

1async function fetchData(): Promise<string> {
2    return "Data received";
3}
4
5fetchData().then((data) => console.log(data)); // "Data received"

Trong ví dụ này, vì hàm async luôn trả về một Promise, giá trị trả về sẽ tự động được xử lý bằng Promise.resolve. Nói cách khác, "Dữ liệu nhận được" trở thành một Promise<string> và được xử lý như một hoạt động bất đồng bộ.

Từ khóa await

Từ khóa await chỉ có thể được sử dụng bên trong một hàm async. Điều này cho phép tạm dừng và chờ kết quả của một Promise trước khi tiếp tục thực hiện hàm.

Trong ví dụ sau, việc xử lý bất đồng bộ sử dụng fetch được viết với async/await.

 1async function getUserData() {
 2    try {
 3        const response = await fetch("https://codesparklab.com/json/example.json");
 4        const data = await response.json();
 5        console.log(data);
 6    } catch (error) {
 7        console.error("Error fetching user data:", error);
 8    }
 9}
10
11getUserData();

Trong ví dụ này, await được sử dụng để đợi hoàn thành Promise trả về từ hàm fetch, và kết quả của nó được gán cho biến response. Sau đó, kết quả của response.json() cũng được xử lý với await.

Xử lý lỗi với async/await

Lỗi xảy ra trong quá trình xử lý bất đồng bộ có thể được bắt bằng cú pháp try...catch chuẩn. Nếu một lỗi xảy ra ở phần await, lỗi đó sẽ được xử lý trong khối catch.

 1async function fetchDataWithErrorHandling() {
 2    try {
 3        const response = await fetch('https://invalid.codesparklab.com/');
 4        if (!response.ok) {
 5            throw new Error(`HTTP error! status: ${response.status}`);
 6        }
 7        const data = await response.json();
 8        console.log(data);
 9    } catch (error) {
10        console.error("Fetch error:", error);
11    }
12}
13
14fetchDataWithErrorHandling();

Trong ví dụ trên, kết quả của hàm fetch được chờ đợi với await, và nếu có lỗi xảy ra, nó sẽ được xử lý với try...catch.

Ưu điểm của async/await

  1. Xử lý bất đồng bộ trực quan: Bằng cách sử dụng async/await, luồng mã trở nên trực quan hơn so với sử dụng chuỗi Promise (then hoặc catch), cho phép viết mã như một quy trình đồng bộ.

  2. Xử lý lỗi dễ dàng: Sử dụng try...catch đơn giản hóa việc xử lý lỗi trong các hoạt động bất đồng bộ. Bạn có thể viết mã dễ đọc hơn so với việc sử dụng chuỗi Promise.

Giá trị trả về của các hàm async

Một hàm async luôn trả về một Promise. Do đó, ngay cả khi không trả về một Promise rõ ràng, xử lý bất đồng bộ vẫn có thể thực hiện được bằng cách sử dụng từ khóa async.

1async function example() {
2    return 42;
3}
4
5example().then((result) => console.log(result)); // 42

Trong đoạn mã trên, một giá trị đồng bộ 42 được trả về, nhưng vì nó nằm trong một hàm async, nên nó tự động được chuyển thành Promise.resolve(42).

Thực thi tuần tự các hàm bất đồng bộ

Khi thực thi nhiều hàm bất đồng bộ liên tiếp, bạn có thể sử dụng await để kiểm soát thứ tự của chúng.

 1async function fetchData(url: string): Promise<any> {
 2    try {
 3        const response = await fetch(url);
 4        return await response.json();
 5    } catch (error) {
 6        console.error("Error fetching user data:", error);
 7    }
 8}
 9
10async function fetchData1(): Promise<any> {
11    return await fetchData("https://codesparklab.com/json/example.json");
12}
13
14async function fetchData2(): Promise<any> {
15    return await fetchData("https://codesparklab.com/json/example2.json");
16}
17
18async function processData() {
19    const data1 = await fetchData1();
20    console.log(data1);
21
22    const data2 = await fetchData2();
23    console.log(data2);
24}
25
26processData();

Trong ví dụ này, fetchData2 được thực thi sau khi chờ fetchData1 hoàn thành. Điều này dễ đọc hơn so với sử dụng chuỗi Promise.

Thực thi song song

Nếu bạn muốn thực hiện các thao tác bất đồng bộ song song, bạn có thể sử dụng Promise.all để xử lý đồng thời nhiều Promise.

 1async function fetchData(url: string): Promise<any> {
 2    try {
 3        const response = await fetch(url);
 4        return await response.json();
 5    } catch (error) {
 6        console.error("Error fetching user data:", error);
 7    }
 8}
 9
10async function fetchData1(): Promise<any> {
11    return await fetchData("https://codesparklab.com/json/example.json");
12}
13
14async function fetchData2(): Promise<any> {
15    return await fetchData("https://codesparklab.com/json/example2.json");
16}
17
18async function fetchMultipleData() {
19    const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
20    console.log(data1);
21    console.log(data2);
22}
23
24fetchMultipleData();

Trong trường hợp này, fetchData1fetchData2 được thực thi cùng lúc, và quá trình tiếp tục sau khi cả hai được hoàn thành. Điều này cho phép xử lý hiệu quả nhiều thao tác bất đồng bộ.

Tóm tắt

  • Một hàm async trả về một Promise, và bằng cách sử dụng từ khóa await, bạn có thể chờ kết quả của một thao tác bất đồng bộ.
  • Bằng cách sử dụng try...catch, việc xử lý lỗi trong các thao tác bất đồng bộ trở nên đơn giản hơn.
  • Bằng cách sử dụng Promise.all, có thể thực hiện nhiều thao tác bất đồng bộ song song.

async/await được sử dụng rộng rãi trong TypeScript và JavaScript vì nó cho phép mô tả các thao tác bất đồng bộ một cách đơn giản hơn.

Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.

YouTube Video