series Axios Bài 2: Khởi Tạo Axios Instance Chuẩn Kiến Trúc Và Master Trọn Bộ CRUD
Khi bước vào một dự án Professional, việc đầu tiên một kỹ sư cần làm trước khi viết tính năng là thiết lập một Trình quản lý API tập trung. Chúng ta sẽ sử dụng tính năng Axios Instance để gom toàn bộ cấu hình mạng về một mối, giúp code luôn "sạch" và cực kỳ dễ bảo trì.
1. Tại sao phải dùng Axios Instance?
Hãy tưởng tượng bạn có 50 file trong mã nguồn cần gọi API. Nếu dùng Axios mặc định, bạn sẽ phải lặp đi lặp lại việc viết Domain của Server, cấu hình Header bảo mật, cấu hình thời gian chờ (Timeout)...
Axios Instance cho phép bạn tạo ra một "bản sao tùy biến" của Axios. Bản sao này sẽ mang sẵn tất cả các cấu hình chung của dự án. Khi cần gọi API, các file tính năng chỉ cần lôi bản sao này ra dùng là xong.
2. Thực Chiến: Khởi Tạo axiosClient
Hãy tạo một file có đường dẫn src/api/axiosClient.js (hoặc .ts nếu dùng TypeScript) với nội dung chuẩn Production như sau:
import axios from 'axios';
// 1. Tạo một instance với các cấu hình mặc định
const axiosClient = axios.create({
baseURL: process.env.REACT_APP_API_URL || 'https://api.myservice.com/v1',
timeout: 10000, // 10 giây chờ, quá thời gian này request sẽ tự hủy để tránh nghẽn app
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
});
export default axiosClient;
- baseURL: Đường dẫn gốc của Server API. Nó nên được đọc từ file môi trường (.env) để dễ dàng chuyển đổi giữa môi trường Test (Staging) và Production.
- timeout: Đảm bảo app không bị treo vô hạn nếu Server gặp sự cố hoặc mạng của người dùng quá yếu.
3. Làm Chủ Trọn Bộ CRUD Với Instance Vừa Tạo
Bây giờ, chúng ta sẽ tạo một file riêng để quản lý các API liên quan đến thực thể User (ví dụ: src/api/userApi.js). Chúng ta sẽ sử dụng cú pháp async/await hiện đại để code trông như một dòng chảy tuyến tính, rất scannable.
import axiosClient from './axiosClient';
const userApi = {
// [READ] - Lấy danh sách users (GET)
getAll(params) {
const url = '/users';
return axiosClient.get(url, { params });
// params ở đây sẽ tự biến thành query string, ví dụ: /users?page=1&limit=10
},
// [READ] - Lấy chi tiết 1 user theo ID (GET)
getById(id) {
const url = `/users/${id}`;
return axiosClient.get(url);
},
// [CREATE] - Tạo mới một user (POST)
create(data) {
const url = '/users';
return axiosClient.post(url, data); // data là object chứa thông tin user mới
},
// [UPDATE] - Cập nhật toàn bộ thông tin user (PUT)
update(id, data) {
const url = `/users/${id}`;
return axiosClient.put(url, data);
},
// [DELETE] - Xóa một user (DELETE)
delete(id) {
const url = `/users/${id}`;
return axiosClient.delete(url);
}
};
export default userApi;
Phân biệt nhanh PUT vs PATCH: > Trong trọn bộ CRUD, khi cần cập nhật dữ liệu bạn sẽ gặp hai phương thức: PUT và PATCH.
- PUT: Dùng khi bạn muốn thay thế hoàn toàn bản ghi cũ bằng một dữ liệu mới. Bạn phải gửi lên toàn bộ các trường dữ liệu.
- PATCH: Dùng khi bạn chỉ muốn chỉnh sửa cục bộ (ví dụ: chỉ đổi mỗi cái ảnh đại diện). Bạn chỉ cần gửi lên đúng trường cần đổi, giúp tiết kiệm băng thông đường truyền.
4. Bắt Lỗi (Error Handling) Sao Cho Đúng Tầm Kỹ Sư?
Một lỗi phổ biến của các bạn mới học là luôn viết block catch(error) và gõ console.log(error). Khi hệ thống chạy thật, người dùng sẽ không mở F12 lên xem log. Bạn cần phân tách rõ ràng các loại lỗi để đưa ra thông báo phù hợp trên giao diện UI.
Khi Axios gặp lỗi, object error trả về sẽ chứa các thông tin chiến lược sau:
try {
const response = await userApi.getById(123);
console.log('Dữ liệu trả về:', response.data);
} catch (error) {
if (error.response) {
// 1. Lỗi từ phía Server trả về (Server nhận được request nhưng từ chối, ví dụ: 401, 403, 404, 500)
console.log('Status Code:', error.response.status);
console.log('Message từ Server:', error.response.data.message);
// Mẹo: Thường dùng để hiển thị thông báo như "Tài khoản không tồn tại" hoặc "Bạn không có quyền".
} else if (error.request) {
// 2. Lỗi do không gửi được request (Mất mạng, Server sập hoàn toàn, lỗi CORS)
console.log('Không nhận được phản hồi từ Server:', error.request);
// Mẹo: Hiển thị thông báo "Vui lòng kiểm tra lại kết nối Internet".
} else {
// 3. Lỗi xảy ra trong quá trình thiết lập request ở code của bạn
console.log('Lỗi cấu hình code:', error.message);
}
}
Tóm lại là...
Bằng cách tách biệt cấu hình chung (axiosClient) và các API cụ thể (userApi), cấu trúc dự án của bạn đã đạt chuẩn Clean Architecture. Code của bạn lúc này cực kỳ dễ đọc, dễ viết Unit Test và kiểm soát lỗi chặt chẽ.
Ở bài học số 3, chúng ta sẽ bước vào tính năng "ma thuật" nhất của Axios, thứ ăn đứt hoàn toàn Fetch API: Làm chủ Axios Interceptors (Bộ đánh chặn) để tự động đính kèm Token bảo mật vào mọi Request và tự động Refresh Token khi hết hạn một cách mượt mà.
All Rights Reserved