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.

Xuất bản: 10 thg 6, 2026Cập nhật: 10 thg 6, 2026Thời gian đọc: 5 minLượt xem: 2
JavaScriptAbortControllerfetchhủy requestlập trình web

💡Đ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

Ảnh minh họa code lập trình
Ảnh minh họa code lập trình

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ụ

Bạn mở app giao đồ ăn. App đang tải danh sách quán ăn ở Quận 1. Bạn đổi sang Quận 3. Danh sách Quận 1 không còn cần nữa.

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ụ

Dừng việc cũ lại. Tôi không cần kết quả đó nữa.

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.

JAVASCRIPT
const controller = new AbortController();

Dòng trên giống như tạo ra một nút hủy.

JAVASCRIPT
controller.abort();

Dòng trên giống như bấm nút hủy.

Cách nhớ:

TEXT
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ụ

áo

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ụ

áo khoác

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

JAVASCRIPT
const controller = new AbortController();

fetch("https://example.com/data", {
    signal: controller.signal
});

controller.abort();

Giải thích:

JAVASCRIPT
const controller = new AbortController();

Tạo nút hủy.

Ví dụ

signal: controller.signal

Đưa tín hiệu hủy cho fetch.

JAVASCRIPT
controller.abort();

Bấm hủy.

Cách hiểu đời thường:

Ví dụ

Tôi giao một việc. Tôi đưa kèm một nút hủy. Khi không cần nữa, tôi bấm hủy.

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.

JAVASCRIPT
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 asyncawait. 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”

JAVASCRIPT
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:

TEXT
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.

JAVASCRIPT
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ụ

Người dùng tìm "áo". Chương trình bắt đầu tải. Người dùng gõ tiếp "áo khoác". Chương trình hủy yêu cầu "áo". Chương trình tải kết quả mới cho "áo khoác".

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:

JAVASCRIPT
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ột nút hủy đã bấm rồi thì không nên dùng lại cho việc mới.

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ụ

AbortController giống như người nói “dừng lại”. Nhưng công việc đó phải biết nghe lệnh dừng.

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ụ

Ô tìm kiếm sản phẩm. Trang chi tiết sản phẩm. Bản đồ đang tải vị trí. Ứng dụng chat tải tin nhắn cũ. Form gửi dữ liệu nhưng người dùng bấm hủy.

11. Lỗi thường gặp

Lỗi 1: Quên truyền signal vào fetch

Sai:

JAVASCRIPT
const controller = new AbortController();

fetch("https://example.com/data");

controller.abort();

Đúng:

JAVASCRIPT
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.

JAVASCRIPT
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

JAVASCRIPT
const controller = new AbortController();

fetch("https://example.com/data", {
    signal: controller.signal
});

Đáp án bài 3

JAVASCRIPT
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:

TEXT
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

  1. MDN Web Docs — AbortController: https://developer.mozilla.org/en-US/docs/Web/API/AbortController
  2. MDN Web Docs — AbortSignal: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
  3. MDN Web Docs — AbortController.abort(): https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort
  4. MDN Web Docs — Fetch API: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
  5. Wikimedia Commons — ảnh minh họa code: https://commons.wikimedia.org/wiki/File:Colorful_code_(Unsplash).jpg
PR

Đượ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.