Phát triển web
JavaScript thực tế: Hủy việc đang tải bằng AbortController
Bài viết giải thích cách sử dụng AbortController trong JavaScript để hủy các request fetch khi người dùng đổi ý, kèm ví dụ thực tế và các lỗi thường gặp.
💡Điểm chính của bài viết
- Bài viết giải thích cách sử dụng AbortController trong JavaScript để hủy các request fetch khi người dùng đổi ý, kèm ví dụ thực tế và các lỗi thường gặp.
Chủ đề: JavaScript thực tế cho người mới
Đối tượng: người đã biết sơ qua console.log, biến và if / else
Mức độ: dễ hiểu, hạn chế thuật ngữ
Ý chính: khi người dùng đổi ý, ta nên biết cách hủy một việc đang chạy dở
Ảnh minh họa: ảnh JPEG từ internet, không nhúng base64, không dùng SVG

Nguồn ảnh: Wikimedia Commons — Colorful code (Unsplash).jpg.
Tác giả ảnh: Markus Spiske.
Giấy phép: CC0 1.0 Public Domain Dedication theo trang Wikimedia Commons.
Trang ảnh gốc: https://commons.wikimedia.org/wiki/File:Colorful_code_(Unsplash).jpg
Link ảnh hiển thị trực tiếp: https://upload.wikimedia.org/wikipedia/commons/thumb/9/94/Colorful_code_%28Unsplash%29.jpg/1280px-Colorful_code_%28Unsplash%29.jpg
1. Vì sao nên học chủ đề này?
Khi mới học JavaScript, nhiều người thường học biến, điều kiện, vòng lặp và hàm. Các phần đó rất quan trọng. Nhưng khi làm website thực tế, bạn sẽ gặp thêm một vấn đề: làm sao hủy một việc đang chạy dở khi nó không còn cần nữa.
Ví dụ đời thường:
Ví dụ
Nếu app vẫn tiếp tục tải dữ liệu cũ, nó có thể tốn mạng, làm chậm trang, hoặc tệ hơn là hiển thị nhầm kết quả cũ. Vì vậy chương trình cần biết cách nói:
Ví dụ
Trong JavaScript, một cách để làm việc này là dùng AbortController.
2. Hiểu thật đơn giản: AbortController là nút hủy
Đừng vội xem AbortController là thuật ngữ khó. Hãy hiểu nó giống như một nút hủy.
const controller = new AbortController();
Dòng trên giống như tạo ra một nút hủy.
controller.abort();
Dòng trên giống như bấm nút hủy.
Cách nhớ:
AbortController = cái nút hủy
abort() = bấm hủy
signal = dây báo cho việc đang chạy biết là đã bị hủy
3. Khi nào cần hủy?
Một ví dụ rất gần với website thật là ô tìm kiếm.
Người dùng gõ:
Ví dụ
Website bắt đầu tải kết quả cho từ khóa “áo”. Nhưng ngay sau đó người dùng gõ tiếp:
Ví dụ
Lúc này kết quả “áo” có thể không còn cần nữa. Ta chỉ cần kết quả “áo khoác”. Nếu yêu cầu cũ về sau yêu cầu mới, trang có thể hiển thị nhầm kết quả.
Đây là kiểu lỗi người mới ít nghĩ tới, nhưng khi làm ứng dụng thật thì gặp khá nhiều.
4. Ví dụ nhỏ nhất
const controller = new AbortController();
fetch("https://example.com/data", {
signal: controller.signal
});
controller.abort();
Giải thích:
const controller = new AbortController();
Tạo nút hủy.
Ví dụ
Đưa tín hiệu hủy cho fetch.
controller.abort();
Bấm hủy.
Cách hiểu đời thường:
Ví dụ
5. Ví dụ có xử lý lỗi
Khi việc tải bị hủy, chương trình thường đi vào phần catch. Người mới có thể hiểu catch là nơi xử lý khi có chuyện không như mong muốn.
const controller = new AbortController();
async function loadData() {
try {
const response = await fetch("https://example.com/data", {
signal: controller.signal
});
const data = await response.json();
console.log(data);
} catch (error) {
console.log("Đã hủy hoặc có lỗi xảy ra");
}
}
loadData();
controller.abort();
Chưa cần hiểu sâu async và await. Tạm hiểu chúng giúp chương trình chờ dữ liệu trả về theo cách dễ đọc hơn.
6. Ví dụ thực tế: nút “Tải” và nút “Hủy”
let controller;
async function startLoading() {
controller = new AbortController();
try {
console.log("Bắt đầu tải...");
const response = await fetch("https://example.com/data", {
signal: controller.signal
});
const data = await response.json();
console.log("Tải xong:", data);
} catch (error) {
console.log("Việc tải đã bị hủy hoặc gặp lỗi.");
}
}
function cancelLoading() {
controller.abort();
console.log("Đã bấm hủy.");
}
Cách hiểu:
startLoading() bắt đầu tải dữ liệu.
cancelLoading() hủy việc tải đang chạy.
Trên trang web thật, startLoading() có thể gắn với nút “Tải dữ liệu”, còn cancelLoading() gắn với nút “Hủy”.
7. Ví dụ tìm kiếm sản phẩm
Đây là ví dụ rất đáng học.
let controller;
async function searchProducts(keyword) {
if (controller) {
controller.abort();
}
controller = new AbortController();
try {
const response = await fetch("/search?q=" + keyword, {
signal: controller.signal
});
const data = await response.json();
console.log("Kết quả mới:", data);
} catch (error) {
console.log("Yêu cầu cũ đã bị hủy.");
}
}
Cách hoạt động:
Ví dụ
8. Lưu ý: không dùng lại controller đã hủy
Một lỗi dễ gặp là dùng lại controller cũ sau khi đã hủy.
Không nên:
const controller = new AbortController();
controller.abort();
fetch("https://example.com/data", {
signal: controller.signal
});
Controller này đã bị hủy rồi. Nếu dùng lại, việc mới có thể bị hủy ngay.
Cách nhớ:
Ví dụ
Mỗi lần bắt đầu một việc mới, nên tạo controller mới.
9. AbortController không tự hủy mọi thứ
AbortController chỉ gửi tín hiệu hủy. Việc đang chạy phải biết nghe tín hiệu đó.
fetch có thể nhận signal, nên nó có thể bị hủy. Nhưng không phải mọi đoạn code đều tự dừng chỉ vì bạn tạo AbortController.
Cách hiểu:
Ví dụ
10. Khi nào nên dùng?
Nên nghĩ đến AbortController khi:
- người dùng có thể bấm hủy;
- người dùng chuyển trang;
- người dùng gõ tìm kiếm liên tục;
- dữ liệu cũ không còn cần nữa;
- muốn tránh hiển thị nhầm kết quả cũ;
- muốn giảm việc tải không cần thiết.
Ví dụ thực tế:
Ví dụ
11. Lỗi thường gặp
Lỗi 1: Quên truyền signal vào fetch
Sai:
const controller = new AbortController();
fetch("https://example.com/data");
controller.abort();
Đúng:
const controller = new AbortController();
fetch("https://example.com/data", {
signal: controller.signal
});
controller.abort();
Lỗi 2: Dùng lại controller đã hủy
Sau khi đã gọi abort(), nên tạo controller mới cho việc mới.
Lỗi 3: Nghĩ hủy là lỗi nguy hiểm
Khi hủy, code có thể đi vào catch. Nhưng điều này không phải lúc nào cũng là lỗi nghiêm trọng. Đôi khi chỉ là người dùng đã bấm hủy hoặc đã đổi ý.
12. Bài tập nhỏ
Bài 1
Tạo một AbortController và in controller.signal.
const controller = new AbortController();
console.log(controller.signal);
Bài 2
Viết một đoạn fetch có truyền signal.
Bài 3
Viết hàm cancelLoading() để hủy việc tải.
Bài 4
Giải thích bằng lời: vì sao ô tìm kiếm nên hủy yêu cầu cũ khi người dùng gõ tiếp?
13. Đáp án gợi ý
Đáp án bài 2
const controller = new AbortController();
fetch("https://example.com/data", {
signal: controller.signal
});
Đáp án bài 3
let controller = new AbortController();
function cancelLoading() {
controller.abort();
}
Đáp án bài 4
Vì kết quả cũ có thể không còn đúng với điều người dùng đang tìm. Nếu không hủy, website có thể tốn mạng, chậm hơn hoặc hiển thị kết quả cũ sau khi người dùng đã nhập từ khóa mới.
14. Ghi nhớ nhanh
AbortController là nút hủy.
controller.signal là tín hiệu gửi cho việc đang chạy.
controller.abort() là bấm hủy.
Dùng khi việc cũ không còn cần nữa.
Rất hữu ích với fetch, tìm kiếm, chuyển trang, nút hủy và giao diện người dùng.
Mỗi việc mới nên có controller mới.
15. Kết luận
AbortController là một kiến thức rất hữu ích khi làm website thực tế. Nó giúp xử lý tình huống người dùng đổi ý, chuyển trang, bấm hủy hoặc nhập tìm kiếm quá nhanh.
Hiểu đơn giản nhất:
AbortController = tạo nút hủy.
signal = đưa nút hủy cho công việc.
abort() = bấm hủy.
Nếu đã biết biến, hàm và fetch, đây là chủ đề rất đáng học tiếp.
Gợi ý tiêu đề SEO
- AbortController là gì trong JavaScript? Giải thích dễ hiểu cho người mới
- Cách hủy fetch request trong JavaScript bằng AbortController
- JavaScript thực tế: hủy việc đang tải khi người dùng đổi ý
- JavaScript thực tế: AbortController và signal
Mô tả SEO
Bài viết giải thích AbortController trong JavaScript theo cách dễ hiểu cho người mới, gồm ví dụ đời thường, cách hủy fetch request, signal, abort, lỗi thường gặp và bài tập thực hành.
Nguồn tham khảo
- MDN Web Docs — AbortController: https://developer.mozilla.org/en-US/docs/Web/API/AbortController
- MDN Web Docs — AbortSignal: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
- MDN Web Docs — AbortController.abort(): https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort
- MDN Web Docs — Fetch API: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
- Wikimedia Commons — ảnh minh họa code: https://commons.wikimedia.org/wiki/File:Colorful_code_(Unsplash).jpg
Được biên soạn bởi PixelRouter Editorial Team
Chúng tôi cung cấp các bài viết chuyên sâu và chính xác về hạ tầng AI, bảo mật API, quản lý tài chính đám mây và tối ưu hóa hệ thống cho nhà phát triển.
Câu hỏi thường gặp
AbortController dùng để làm gì trong JavaScript?
AbortController tạo ra một nút hủy, cho phép bạn gửi tín hiệu hủy (signal) tới các tác vụ đang chạy như fetch, để dừng chúng khi không còn cần thiết.
Làm sao truyền signal vào fetch để có thể hủy yêu cầu?
Bạn truyền đối tượng signal vào tùy chọn của fetch: ```javascript fetch(url, { signal: controller.signal }) ```
Khi nào nên tạo một AbortController mới?
Mỗi khi bắt đầu một tác vụ mới (ví dụ: một lần fetch mới, một lần tìm kiếm mới) cần tạo một AbortController mới; không nên dùng lại controller đã bị abort.
Nếu quên truyền signal vào fetch thì abort có hiệu lực không?
Không. Nếu không truyền controller.signal vào fetch, việc gọi controller.abort() sẽ không dừng được yêu cầu fetch.
Các lỗi thường gặp khi sử dụng AbortController là gì?
Ba lỗi phổ biến: 1) Quên truyền signal vào fetch, 2) Dùng lại controller đã bị abort, 3) Nhầm lẫn rằng abort luôn là lỗi nghiêm trọng – thực tế nó chỉ dẫn tới khối catch khi người dùng hủy.