Các yêu cầu HTTP là một phần cơ bản của phát triển web hiện đại. Với sự ra mắt của Fetch API trong Node.js, các nhà phát triển giờ đây có một cách mạnh mẽ và nhất quán để thực hiện các yêu cầu mạng qua cả môi trường trình duyệt và máy chủ. Trong hướng dẫn toàn diện này, chúng ta sẽ khám phá cách sử dụng Node fetch hiệu quả trong các dự án của bạn.
Node Fetch API là gì và Tại sao bạn nên sử dụng nó?
Node fetch API là một cơ chế hiện đại, dựa trên promise để thực hiện các yêu cầu HTTP trong các ứng dụng Node.js. Ban đầu là một tính năng chỉ dành cho trình duyệt, fetch đã trở thành một tính năng thử nghiệm trong Node.js v18 và đạt được tính ổn định trong Node.js v21.
Lợi ích chính của việc sử dụng Node Fetch:
- Chức năng tích hợp sẵn: Không cần cài đặt các gói của bên thứ ba
- Dựa trên promise: Cú pháp sạch, hiện đại với hỗ trợ async/await
- Thân thuộc đa nền tảng: Cùng API như fetch ở phía trình duyệt
- Hiệu suất cải thiện: Được xây dựng trên client HTTP Undici hiệu suất cao
Kiểm tra các yêu cầu Node Fetch API của bạn bằng các công cụ hiện đại
Khi học cách sử dụng Node fetch, việc có các công cụ đáng tin cậy để kiểm tra các điểm cuối API là rất quan trọng. Apidog nổi bật như là sự thay thế tốt nhất cho Postman để kiểm tra và tài liệu hóa các yêu cầu Node fetch API của bạn.

Là một nền tảng phát triển API tất cả trong một, Apidog kết hợp tài liệu API, kiểm tra và máy chủ giả lập trong một giao diện trực quan duy nhất.

Khi phát triển ứng dụng với Node fetch, Apidog giúp bạn hình dung các phản hồi, hợp tác với các thành viên trong nhóm, và đảm bảo rằng các cuộc gọi API của bạn hoạt động chính xác trước khi triển khai chúng trong mã. Khả năng tạo đoạn mã cho các yêu cầu Node fetch giúp việc chuyển đổi từ kiểm tra sang triển khai diễn ra một cách liền mạch.

Thiết lập môi trường của bạn cho Node Fetch
Các yêu cầu trước khi sử dụng Node Fetch
Trước khi đi vào các ví dụ về Node fetch, hãy đảm bảo bạn có:
- Node.js v18 trở lên (tốt nhất là v21+ để hỗ trợ fetch ổn định)
- Kiểm tra phiên bản Node.js của bạn:
node -v
Tính tương thích phiên bản Node Fetch
- Node.js v21+: Fetch ổn định và sẵn sàng cho việc sử dụng sản xuất
- Node.js v18-v20: Fetch có sẵn nhưng thử nghiệm (sử dụng cờ
-experimental-fetch
) - Các phiên bản Node.js cũ hơn: Cài đặt gói
node-fetch
hoặc nâng cấp Node.js
Nếu bạn đang sử dụng v18-v20, hãy chạy ứng dụng của bạn với:
node --experimental-fetch app.js
Thực hiện yêu cầu Node Fetch đầu tiên của bạn
Hãy bắt đầu với một yêu cầu GET cơ bản bằng Node fetch:
// Yêu cầu GET cơ bản với Node fetch
fetch('<https://api.example.com/data>')
.then(response => {
if (!response.ok) {
throw new Error(`Lỗi HTTP! Trạng thái: ${response.status}`);
}
return response.json(); // Phân tích phản hồi JSON
})
.then(data => {
console.log('Dữ liệu nhận được:', data);
})
.catch(error => {
console.error('Lỗi Fetch:', error);
});
Sử dụng Node Fetch với Async/Await
Để mã gọn gàng hơn, bạn có thể sử dụng async/await với Node fetch:
async function fetchData() {
try {
const response = await fetch('<https://api.example.com/data>');
if (!response.ok) {
throw new Error(`Lỗi HTTP! Trạng thái: ${response.status}`);
}
const data = await response.json();
console.log('Dữ liệu nhận được:', data);
return data;
} catch (error) {
console.error('Lỗi Fetch:', error);
}
}
// Gọi hàm
fetchData();
Các phương thức yêu cầu Node Fetch nâng cao
Thực hiện các yêu cầu POST với Node Fetch
async function postData(url, data) {
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Lỗi HTTP! Trạng thái: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Lỗi Fetch POST:', error);
}
}
// Ví dụ sử dụng
const newUser = {
name: 'John Doe',
email: 'john@example.com',
};
postData('<https://api.example.com/users>', newUser)
.then(data => console.log('Người dùng đã tạo:', data));
Các yêu cầu PUT với Node Fetch
async function updateData(url, data) {
try {
const response = await fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Lỗi HTTP! Trạng thái: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Lỗi Fetch PUT:', error);
}
}
// Ví dụ sử dụng
const updatedUser = {
id: 1,
name: 'Jane Smith',
email: 'jane@example.com',
};
updateData('<https://api.example.com/users/1>', updatedUser)
.then(data => console.log('Người dùng đã cập nhật:', data));
Các yêu cầu DELETE với Node Fetch
async function deleteResource(url) {
try {
const response = await fetch(url, {
method: 'DELETE',
});
if (!response.ok) {
throw new Error(`Lỗi HTTP! Trạng thái: ${response.status}`);
}
// Một số API không trả về nội dung khi DELETE
if (response.status === 204) {
return { success: true };
}
return await response.json();
} catch (error) {
console.error('Lỗi Fetch DELETE:', error);
}
}
// Ví dụ sử dụng
deleteResource('<https://api.example.com/users/1>')
.then(result => console.log('Kết quả xoá:', result));
Xử lý các loại phản hồi khác nhau với Node Fetch
Node fetch có thể làm việc với nhiều định dạng phản hồi khác nhau:
Xử lý phản hồi JSON
fetch('<https://api.example.com/data>')
.then(response => response.json())
.then(data => console.log(data));
Xử lý phản hồi văn bản
fetch('<https://example.com/plain-text>')
.then(response => response.text())
.then(text => console.log(text));
Xử lý dữ liệu nhị phân
fetch('<https://example.com/image.png>')
.then(response => response.arrayBuffer())
.then(buffer => {
// Xử lý dữ liệu nhị phân
const bytes = new Uint8Array(buffer);
console.log('Độ dài dữ liệu nhị phân:', bytes.length);
});
Tùy chỉnh các yêu cầu Node Fetch với tiêu đề và tùy chọn
Thiết lập tiêu đề tùy chỉnh
fetch('<https://api.example.com/protected-data>', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN_HERE',
'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'My Node.js Application'
}
})
.then(response => response.json())
.then(data => console.log(data));
Cấu hình các tùy chọn yêu cầu
fetch('<https://api.example.com/data>', {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
cache: 'no-cache',
redirect: 'follow', // làm theo, lỗi, hoặc thủ công
referrerPolicy: 'no-referrer'
})
.then(response => response.json())
.then(data => console.log(data));
Xử lý lỗi với Node Fetch
Xử lý lỗi toàn diện
Một khía cạnh quan trọng cần hiểu về Node fetch là nó không từ chối trên các mã trạng thái lỗi HTTP. Promise chỉ từ chối khi có lỗi mạng hoặc nếu điều gì đó ngăn cản yêu cầu hoàn thành.
Dưới đây là một cách tiếp cận xử lý lỗi toàn diện:
async function fetchWithErrorHandling(url) {
try {
const response = await fetch(url);
// Kiểm tra lỗi HTTP
if (!response.ok) {
// Cố gắng lấy chi tiết lỗi từ phản hồi
let errorDetails;
try {
errorDetails = await response.json();
} catch (e) {
errorDetails = await response.text();
}
throw new Error(
`Lỗi HTTP! Trạng thái: ${response.status}, Chi tiết: ${
typeof errorDetails === 'object'
? JSON.stringify(errorDetails)
: errorDetails
}`
);
}
return await response.json();
} catch (error) {
// Lỗi mạng, lỗi phân tích và các lỗi HTTP tùy chỉnh của chúng tôi
console.error('Fetch failed:', error.message);
throw error; // Ném lại để cho phép mã gọi xử lý
}
}
Triển khai thời gian chờ yêu cầu với Node Fetch
Node fetch không có hỗ trợ thời gian chờ tích hợp, nhưng bạn có thể triển khai nó bằng AbortController
:
async function fetchWithTimeout(url, options = {}, timeoutMs = 5000) {
const controller = new AbortController();
const { signal } = controller;
// Thiết lập thời gian chờ
const timeout = setTimeout(() => {
controller.abort();
}, timeoutMs);
try {
const response = await fetch(url, { ...options, signal });
clearTimeout(timeout); // Xoá thời gian chờ nếu fetch hoàn thành
if (!response.ok) {
throw new Error(`Lỗi HTTP! Trạng thái: ${response.status}`);
}
return await response.json();
} catch (error) {
clearTimeout(timeout);
if (error.name === 'AbortError') {
throw new Error(`Yêu cầu đã quá thời gian chờ sau ${timeoutMs}ms`);
}
throw error;
}
}
// Ví dụ sử dụng
fetchWithTimeout('<https://api.example.com/data>', {}, 3000)
.then(data => console.log(data))
.catch(error => console.error('Lỗi:', error.message));
Xử lý xác thực với Node Fetch
Xác thực cơ bản
const username = 'user';
const password = 'password';
const credentials = Buffer.from(`${username}:${password}`).toString('base64');
fetch('<https://api.example.com/protected>', {
headers: {
'Authorization': `Basic ${credentials}`
}
})
.then(response => response.json())
.then(data => console.log(data));
Xác thực Bearer Token
const token = 'your_jwt_or_oauth_token';
fetch('<https://api.example.com/protected>', {
headers: {
'Authorization': `Bearer ${token}`
}
})
.then(response => response.json())
.then(data => console.log(data));
Những thực tiễn tốt nhất khi sử dụng Node Fetch trong sản xuất
- Luôn kiểm tra trạng thái phản hồi: Đừng giả định rằng các phản hồi là thành công
- Xử lý các loại nội dung khác nhau một cách thích hợp: Sử dụng phương pháp đúng cho loại phản hồi của bạn (json(), text(), v.v.)
- Thực hiện xử lý lỗi đúng cách: Tạo các hàm tiện ích xử lý lỗi một cách nhất quán
- Thiết lập thời gian chờ yêu cầu: Ngăn chặn các yêu cầu treo với AbortController
- Tạo các lớp bao bọc fetch có thể tái sử dụng: Xây dựng một lớp dịch vụ với các mẫu yêu cầu chung
- Cân nhắc logic thử lại cho các yêu cầu không thành công: Triển khai hồi tiếp theo cấp số cho các API không ổn định
- Sử dụng biến môi trường cho các URL cơ sở: Giữ các URL cụ thể của môi trường ra khỏi mã
Khắc phục sự cố Node Fetch phổ biến
Lỗi "Fetch không được định nghĩa"
Nếu bạn gặp ReferenceError: fetch is not defined
, hãy kiểm tra:
- Bạn đang sử dụng Node.js v18+
- Đối với Node.js v18-v20, hãy sử dụng cờ
-experimental-fetch
- Đối với các phiên bản cũ hơn, hãy cài đặt gói
node-fetch
Vấn đề chứng chỉ HTTPS
Node fetch kế thừa việc xử lý chứng chỉ HTTPS của Node. Đối với các chứng chỉ tùy chỉnh:
const https = require('https');
const fs = require('fs');
const httpsAgent = new https.Agent({
ca: fs.readFileSync('./custom-certificate.pem')
});
fetch('<https://api.example.com/data>', {
agent: httpsAgent
})
.then(response => response.json())
.then(data => console.log(data));
Kết luận: Áp dụng Node Fetch trong các dự án của bạn
Node fetch API đại diện cho một sự cải tiến đáng kể trong cách chúng ta thực hiện các yêu cầu HTTP trong các ứng dụng Node.js. Với giao diện dựa trên promise, hành vi nhất quán qua các nền tảng, và việc thực hiện nội tại, nó đang trở thành sự lựa chọn ưu tiên cho phát triển Node.js hiện đại.
Bằng cách làm chủ Node fetch, bạn có thể tạo ra mã dễ bảo trì hơn mà tận dụng các tính năng hiện đại của JavaScript trong khi tận hưởng hiệu suất tốt hơn so với các thư viện client HTTP cũ hơn. Khi việc thực hiện ổn định tiếp tục trưởng thành trong Node.js, chúng ta có thể mong đợi ngày càng nhiều nhà phát triển sẽ áp dụng API mạnh mẽ này như một phương pháp chuẩn để thực hiện các yêu cầu HTTP.
Giờ đây, khi bạn đã có sự hiểu biết toàn diện về Node fetch, bạn đã sẵn sàng để triển khai nó trong các dự án của riêng mình và tận dụng API mạnh mẽ này cho tất cả các nhu cầu yêu cầu HTTP của bạn.