Async/await là gì? Hướng dẫn sử dụng Async/await trong dự án React

Trong phát triển ứng dụng hiện đại, việc xử lý các tác vụ bất đồng bộ là điều không thể thiếu, đặc biệt là trong các ứng dụng React. Nếu bạn đã từng cảm thấy khó khăn khi làm việc với các chuỗi lệnh .then() lồng nhau (thường được gọi là callback hell), thì cú pháp async/await chính là giải pháp giúp bạn đơn giản hóa quá trình này, giúp mã nguồn trở nên dễ hiểu và dễ quản lý hơn.

Hãy cùng khám phá cách async/await hoạt động và lý do tại sao nó trở thành công cụ yêu thích trong JavaScript.

1. Async/Await Là Gì?

Cú pháp async/await là một phần trong JavaScript giúp xử lý các tác vụ bất đồng bộ. Nó dựa trên Promise, một cấu trúc cho phép bạn làm việc với mã bất đồng bộ dễ dàng hơn.

  • async: Khi được thêm vào trước một hàm, từ khóa này sẽ biến hàm đó thành hàm bất đồng bộ, và nó luôn trả về một Promise.
  • await: Được sử dụng bên trong hàm async, có chức năng “chờ” cho Promise hoàn thành trước khi tiếp tục thực hiện các dòng mã tiếp theo.

Cú pháp async/await trong JavaScriptCú pháp async/await trong JavaScript

Có thể hiểu một cách đơn giản:

  • Async/await giúp mã bất đồng bộ trông giống như mã đồng bộ.
  • Thay vì sử dụng phương thức .then() hoặc .catch(), bạn có thể dùng try...catch để bắt lỗi một cách hiệu quả hơn.

Dưới đây là một ví dụ đơn giản về việc lấy danh sách người dùng.

  • Sử dụng Promise và .then():
fetch("https://api.example.com/data")
  .then((response) => response.json())
  .then((data) => {
    console.log("Dữ liệu nhận được:", data);
  })
  .catch((error) => {
    console.error("Lỗi:", error);
  });
  • Sử dụng async/await:
const fetchData = async () => {
  try {
    const response = await fetch("https://api.example.com/data");
    const data = await response.json();
    console.log("Dữ liệu nhận được:", data);
  } catch (error) {
    console.error("Lỗi:", error);
  }
};

fetchData();

Như bạn thấy, sử dụng async/await giúp mã của bạn trở nên rõ ràng và dễ đọc hơn.

2. Tại Sao Nên Sử Dụng Async/Await?

2.1 Ưu điểm

  • Mã viết ra sẽ gọn gàng và dễ theo dõi hơn.
  • try...catch giúp cuốn chuyển và xử lý lỗi ở một nơi, thay vì thêm .catch() vào mỗi Promise.
  • Hỗ trợ mạnh mẽ cho các thư viện khác nhau như React, Node.js.

2.2 Khi Nào Nên Sử Dụng Async/Await?

  • Khi gọi API để lấy dữ liệu trong React.
  • Khi cần thực hiện các tác vụ bất đồng bộ như truy xuất cơ sở dữ liệu, xử lý tệp, hoặc chờ một hiệu ứng đặc biệt hoàn thành.
  • Khi muốn thay thế các đoạn mã Promise phức tạp bằng cú pháp dễ đọc hơn.

3. Hướng Dẫn Sử Dụng Async/Await Trong React

Bây giờ, chúng ta sẽ tìm hiểu cách áp dụng async/await trong một dự án React thông qua một số ví dụ thực tế.

3.1 Lấy Danh Sách Người Dùng Qua API

Mình sẽ tạo một component có tên là UserList để hiển thị danh sách người dùng từ API https://jsonplaceholder.typicode.com/users.

import React, { useState, useEffect } from "react";

const UserList = () => {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const response = await fetch("https://jsonplaceholder.typicode.com/users");
        if (!response.ok) {
          throw new Error("Lỗi mạng, không thể tải dữ liệu");
        }
        const data = await response.json();
        setUsers(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchUsers();
  }, []);

  if (loading) {
    return <p>Đang tải...</p>;
  }

  if (error) {
    return <p>Lỗi: {error}</p>;
  }

  return (
    <div>
      <h1>Danh sách người dùng</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
};

export default UserList;

3.2 Gọi Nhiều API Liên Tiếp

Giả sử bạn cần gọi hai API: một để lấy danh sách người dùng và một để lấy danh sách bài viết. Bạn có thể sử dụng await để đảm bảo các lệnh gọi API được thực hiện theo thứ tự.

import React, { useState, useEffect } from "react";

const PostsAndUsers = () => {
  const [users, setUsers] = useState([]);
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const userResponse = await fetch("https://jsonplaceholder.typicode.com/users");
        if (!userResponse.ok) {
          throw new Error("Lỗi khi tải danh sách người dùng");
        }
        const userData = await userResponse.json();
        setUsers(userData);

        const postResponse = await fetch("https://jsonplaceholder.typicode.com/posts");
        if (!postResponse.ok) {
          throw new Error("Lỗi khi tải danh sách bài viết");
        }
        const postData = await postResponse.json();
        setPosts(postData);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) return <p>Đang tải...</p>;
  if (error) return <p>Lỗi: {error}</p>;

  return (
    <div>
      <h1>Người dùng và Bài viết</h1>
      <h2>Người dùng:</h2>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
      <h2>Bài viết:</h2>
      <ul>
        {posts.slice(0, 10).map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default PostsAndUsers;

3.3 Tích Hợp Với Axios

Axios là thư viện HTTP client phổ biến giúp gọi API dễ dàng và hiệu quả hơn. Nó cũng hỗ trợ Promise, vì vậy bạn hoàn toàn có thể sử dụng async/await với Axios.

Trước tiên, bạn cần cài đặt Axios:

pnpm install axios

Sau đó, bạn có thể sử dụng Axios như sau:

import React, { useState, useEffect } from "react";
import axios from "axios";

const UserListWithAxios = () => {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const response = await axios.get("https://jsonplaceholder.typicode.com/users");
        setUsers(response.data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchUsers();
  }, []);

  if (loading) return <p>Đang tải...</p>;
  if (error) return <p>Lỗi: {error}</p>;

  return (
    <div>
      <h1>Danh sách người dùng (Sử dụng Axios)</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
};

export default UserListWithAxios;

4. Lưu Ý Khi Sử Dụng Async/Await Trong React

  • Không nên gọi async trực tiếp trong useEffect, mà hãy bọc nó trong một hàm con. Điều này giúp bảo đảm rằng useEffect tuân theo quy tắc trả về void hoặc một hàm cleanup.
useEffect(() => {
  const fetchData = async () => {
    // Code async ở đây
  };

  fetchData();
}, []);
  • Nếu component của bạn bị unmount trước khi tác vụ async hoàn tất, việc cập nhật state có thể gây lỗi. Do đó, có thể dùng biến cờ (isMounted) để kiểm tra:
useEffect(() => {
  let isMounted = true;

  const fetchData = async () => {
    try {
      const data = await fetchDataFromAPI();
      if (isMounted) {
        setData(data);
      }
    } catch (error) {
      // Xử lý lỗi
    }
  };

  fetchData();
  return () => {
    isMounted = false;
  };
}, []);
  • Hãy nhớ sử dụng try...catch khi làm việc với async/await để đảm bảo bạn xử lý bất kỳ lỗi nào có thể phát sinh.
  • Cuối cùng, luôn hiển thị trạng thái loading cho người dùng trong khi dữ liệu đang được tải, điều này giúp cải thiện trải nghiệm sử dụng.

5. Kết Luận

Cú pháp async/await mang lại một cách tiếp cận đơn giản và hiệu quả hơn trong việc xử lý các tác vụ bất đồng bộ trong JavaScript, đặc biệt là trong các ứng dụng React. Từ việc gọi API đơn giản tới việc quản lý nhiều thao tác bất đồng bộ, async/await giúp mã nguồn của bạn dễ đọc và bảo trì hơn rất nhiều.

Hy vọng rằng bài viết này sẽ giúp bạn hiểu rõ và áp dụng cú pháp async/await một cách hiệu quả trong dự án React của mình.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *