Cơ bảnKiến thức cơ bản

Fetch API trong JavaScript: Gọi API từ trình duyệt

8 phút đọc9 lượt xem
#fetch api#javascript#gọi api#async await#http request#axios vs fetch#cors

Fetch API trong JavaScript: Gọi API từ trình duyệt

Một số website tự động cập nhật dữ liệu — bài viết mới, thời tiết, thông báo — mà không cần bạn nhấn F5. Đằng sau đó, JavaScript đang gửi request đến server và nhận dữ liệu về. Công cụ thực hiện việc này là Fetch API.

Fetch API là cách chuẩn và hiện đại nhất để gọi API từ trình duyệt — không cần cài thêm thư viện, dựa trên Promise, và kết hợp tốt với async/await.

Sau bài này, bạn làm được: gửi GET và POST request, xử lý Response object đúng cách, viết error handling chuẩn, và hiểu khi nào nên dùng Fetch thay vì Axios.

Yêu cầu trước: Bạn đã biết async/await và hiểu cơ bản về API là gì.

Fetch API là gì?

Fetch API là tính năng tích hợp sẵn trong trình duyệt cho phép JavaScript gửi HTTP request. Ra đời năm 2015, hiện hỗ trợ trên tất cả trình duyệt hiện đại.

Trước Fetch API, lập trình viên dùng XMLHttpRequest — cú pháp rườm rà, khó đọc:

// Cách cũ — không cần học nữa
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1');
xhr.onload = function() {
    if (xhr.status === 200) {
        console.log(JSON.parse(xhr.responseText));
    }
};
xhr.send();

Cùng chức năng đó, Fetch API viết ngắn hơn nhiều:

const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const post = await response.json();
console.log(post);

Cú pháp cơ bản và 2 bước quan trọng

async function layBaiViet() {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
    const post = await response.json();
    console.log(post.title);
}

layBaiViet();

Fetch hoạt động theo 2 bước:

  1. await fetch(url) — Chờ server phản hồi, trả về Response object (chứa header)
  2. await response.json() — Đọc body và chuyển JSON thành object JavaScript

Tại sao cần 2 bước? Dữ liệu được truyền theo luồng (stream) — header đến trước, body đến sau. Thiết kế này cho phép xử lý file lớn mà không cần chờ toàn bộ dữ liệu.

GET Request thực hành

Copy đoạn code này và chạy trong Console trình duyệt (F12 → Console) — dùng JSONPlaceholder, API miễn phí cho học tập:

async function layDanhSachBaiViet() {
    try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts');

        if (!response.ok) {
            throw new Error(`Lỗi server: ${response.status}`);
        }

        const posts = await response.json();

        posts.slice(0, 3).forEach(post => {
            console.log(`[${post.id}] ${post.title}`);
        });

    } catch (error) {
        console.error('Không lấy được dữ liệu:', error.message);
    }
}

layDanhSachBaiViet();

Response Object — Các thuộc tính quan trọng

Thuộc tính / Phương thứcKiểuÝ nghĩa
response.okbooleantrue nếu status 200–299
response.statusnumberHTTP status code (200, 404, 500…)
response.statusTextstring"OK", "Not Found"…
response.json()PromiseParse JSON body thành object
response.text()PromiseĐọc body dưới dạng chuỗi

POST Request — Gửi dữ liệu

async function dangBaiViet(tieuDe, noiDung) {
    try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                title: tieuDe,
                body: noiDung,
                userId: 1,
            }),
        });

        if (!response.ok) {
            throw new Error(`Đăng bài thất bại: ${response.status}`);
        }

        const baiMoi = await response.json();
        console.log('Đã tạo bài viết với ID:', baiMoi.id);
        return baiMoi;

    } catch (error) {
        console.error('Lỗi POST:', error.message);
    }
}

dangBaiViet('Tiêu đề thử nghiệm', 'Nội dung bài viết...');

3 điểm quan trọng khi dùng POST:

  1. method: 'POST' — Mặc định là GET, phải chỉ định rõ
  2. 'Content-Type': 'application/json' — Bắt buộc khi gửi JSON
  3. JSON.stringify() — Chuyển object thành chuỗi JSON trước khi gửi

Xử lý lỗi đúng cách — Điểm hay bị bỏ qua

Fetch API không tự động throw error khi nhận status 404 hay 500. Điều này khác với Axios — và là lý do nhiều người viết sai:

// SAI — Không bắt được lỗi HTTP
async function layDuLieuSai() {
    try {
        const response = await fetch('/api/khong-ton-tai');
        const data = await response.json(); // Vẫn chạy dù server trả 404!
        return data;
    } catch (error) {
        // Chỉ bắt lỗi MẠNG, không bắt lỗi HTTP
        console.error('Lỗi:', error);
    }
}
// ĐÚNG — Kết hợp response.ok với try/catch
async function layDuLieuDung() {
    try {
        const response = await fetch('/api/du-lieu');

        if (!response.ok) {
            throw new Error(`Lỗi HTTP: ${response.status}`);
        }

        return await response.json();

    } catch (error) {
        // Bắt được cả lỗi mạng VÀ lỗi HTTP
        console.error('Lỗi:', error.message);
        return null;
    }
}

CORS là gì và cách xử lý

Khi học Fetch API, bạn sẽ gặp lỗi này:

Access to fetch at 'https://api.other-site.com/data' from origin 
'http://localhost:3000' has been blocked by CORS policy.

CORS là cơ chế bảo mật của trình duyệt. Khi trang web của bạn (localhost:3000) gọi API từ domain khác, trình duyệt mặc định chặn lại.

Cách xử lý:

  1. Server thêm CORS header (cách đúng trong production): Access-Control-Allow-Origin: *
  2. Dùng proxy khi phát triển: Cấu hình proxy trong Vite hoặc webpack-dev-server
  3. Dùng API đã hỗ trợ CORS: JSONPlaceholder, OpenWeatherMap

Lưu ý: CORS là quy tắc của trình duyệt — cùng request đó gửi từ Postman hay Node.js thì hoàn toàn bình thường.

Fetch API so với Axios

Tiêu chíFetch APIAxios
Cài đặtKhông cần (có sẵn)npm install axios
Phát hiện lỗi HTTPPhải tự kiểm tra response.okTự động reject 4xx/5xx
Parse JSONPhải gọi .json() thủ côngTự động
InterceptorKhông cóCó (thêm token, log…)
Node.js supportTừ v18 trở lênMọi phiên bản
Kích thước0 KB~14 KB

Khi nào dùng Fetch: Học tập, dự án cá nhân nhỏ, muốn tránh phụ thuộc thư viện ngoài.

Khi nào dùng Axios: Dự án team vừa-lớn, cần authentication tập trung, muốn error handling nhất quán.

Lời khuyên: Học Fetch trước để hiểu cơ chế — sau đó chuyển sang Axios sẽ rất nhanh.

Thực hành đầy đủ: CRUD với JSONPlaceholder

const BASE_URL = 'https://jsonplaceholder.typicode.com';

async function xuLyResponse(response) {
    if (!response.ok) throw new Error(`Lỗi HTTP ${response.status}`);
    return response.json();
}

async function taoBaiViet(duLieu) {
    const response = await fetch(`${BASE_URL}/posts`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(duLieu),
    });
    return xuLyResponse(response);
}

async function layBaiViet(id) {
    const response = await fetch(`${BASE_URL}/posts/${id}`);
    return xuLyResponse(response);
}

async function xoaBaiViet(id) {
    const response = await fetch(`${BASE_URL}/posts/${id}`, { method: 'DELETE' });
    return response.ok;
}

// Chạy thử
async function main() {
    try {
        const baiMoi = await taoBaiViet({ title: 'Học Fetch API', body: '...', userId: 1 });
        console.log('Đã tạo bài viết, ID:', baiMoi.id);

        const bai = await layBaiViet(1);
        console.log('Tiêu đề:', bai.title);

        const daXoa = await xoaBaiViet(1);
        console.log('Đã xóa:', daXoa);
    } catch (error) {
        console.error('Có lỗi:', error.message);
    }
}

main();

Câu hỏi thường gặp

Fetch có dùng được trên Internet Explorer không?

Không. IE đã ngừng hỗ trợ từ 6/2022 — dự án hiện đại không cần lo về IE.

Tại sao POST của mình gửi nhưng server không nhận được dữ liệu?

Kiểm tra 3 điều: (1) Đã thêm Content-Type: application/json chưa? (2) Đã dùng JSON.stringify() chưa? (3) Server có cấu hình CORS đúng không?

Tóm tắt

  • Fetch API là cách chuẩn để gửi HTTP request từ trình duyệt — không cần cài đặt
  • Dùng async/await + try/catch là cách viết được khuyến nghị
  • Luôn kiểm tra response.ok — Fetch không tự throw lỗi HTTP
  • POST cần method, Content-Type header, và JSON.stringify() cho body
  • CORS là giới hạn của trình duyệt — cần server cho phép hoặc dùng proxy

Bước tiếp theo: Tự viết một trang hiển thị danh sách từ JSONPlaceholder, thêm nút "Xóa" dùng DELETE request. Kết hợp với kiến thức JavaScript cơ bản và bạn đã có thể tự xây ứng dụng web đơn giản.

Về tác giả

Ảnh đại diện tác giả Kenji — họa tiết hình học

Kenji

Kỹ sư phần mềm full-stack (Web), hơn 5 năm kinh nghiệm thực tế

  • Python
  • DB
  • Hạ tầng
  • Đào tạo & cố vấn
  • AI

Làm việc cùng đồng nghiệp người Việt, tôi thấy thiếu tài liệu kỹ thuật rõ ràng bằng tiếng Việt. codeahoc là nơi tôi chia sẻ theo hướng thực tế, dễ áp dụng.

Nguyên tắc nội dung

  • Ưu tiên nguồn gốc và góc nhìn từ thực tế triển khai.
  • Nếu có sai sót, nội dung sẽ được cập nhật và sửa kịp thời.

Khóa học liên quan

The Complete JavaScript Course 2026: From Zero to Expert!

Khóa học JavaScript toàn diện nhất từ cơ bản đến nâng cao.

4.7
Xem khóa học →

React - The Complete Guide (incl. React Router & Redux)

Làm chủ React.js với các dự án thực tế, hooks, Redux.

4.6
Xem khóa học →

Node.js, Express, MongoDB & More: The Complete Bootcamp

Backend với Node.js: REST API, authentication, MongoDB.

4.7
Xem khóa học →

*Đây là liên kết liên kết (affiliate link). Chúng tôi có thể nhận hoa hồng nếu bạn mua khóa học qua liên kết này.