fetch 還有隱藏技能?——原來它可以被取消!
你大概已經用過無數(shù)次 fetch():
const response = await fetch("/api/data");輕輕松松,對吧?
那如果——
- 用戶在請求未完成前跳轉頁面?
 - 你發(fā)起了新請求,應該替換舊請求?
 - 想取消一個長下載或不再需要的網絡調用?
 
多年來,fetch() 沒有“自帶取消”。直到主角登場:AbortController。
AbortController 到底是啥?
AbortController API 能創(chuàng)建一個 signal,把它傳給 fetch,就能隨時中止一個或多個請求。 把它想象成——給你的網絡請求配了個遙控器。
const controller = new AbortController();
const signal = controller.signal;
fetch("/api/data", { signal })
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => {
    if (err.name === "AbortError") {
      console.log("Request was cancelled!");
    } else {
      console.error(err);
    }
  });
// 需要時直接取消
controller.abort();?????? 調用 controller.abort(),請求立刻停止。 ?????? fetch 會以 AbortError 結束,你可以優(yōu)雅處理。
為什么要取消 fetch?
取消不是“錦上添花”,而是性能與體驗必備。真實場景:
- 搜索框:用戶快速輸入,不能每個鍵都發(fā)請求
 - 分頁/篩選:新篩選發(fā)出,舊結果應作廢
 - 導航:離開頁面時,不要讓請求繼續(xù)跑 這些情況下,舊請求是浪費帶寬,還可能引發(fā)競態(tài)(舊結果覆蓋新結果)。
 

?? 場景一:用戶手動取消
<button id="cancel">Cancel</button>
<script>
const controller = new AbortController();
const signal = controller.signal;
fetch("https://jsonplaceholder.typicode.com/photos", { signal })
  .then(res => res.json())
  .then(data => console.log("Fetched:", data))
  .catch(err => {
    if (err.name === "AbortError") {
      console.log("Fetch aborted by user.");
    }
  });
document.getElementById("cancel").addEventListener("click", () => {
  controller.abort();
});
</script>??? 點“Cancel” → 請求立即終止??? catch 分支安全兜底
場景二:新的搜索自動取消舊請求(最常見)
let controller;
async function search(query) {
  if (controller) controller.abort(); // 取消舊請求
  controller = new AbortController();
  try {
    const res = await fetch(`/api/search?q=${query}`, {
      signal: controller.signal,
    });
    const data = await res.json();
    console.log("Results:", data);
  } catch (err) {
    if (err.name === "AbortError") {
      console.log("Old request aborted!");
    } else {
      console.error(err);
    }
  }
}?? 每次新搜索都會自動終止上一次 ?? 避免浪費與過期結果覆蓋
?? 場景三:一把梭取消多個請求
const controller = new AbortController();
Promise.all([
  fetch("/api/user", { signal: controller.signal }),
  fetch("/api/posts", { signal: controller.signal }),
]).catch(err => {
  if (err.name === "AbortError") {
    console.log("All requests aborted.");
  }
});
// 一鍵全停
controller.abort();適合儀表盤、批量加載等并發(fā)場景。
Abort 之后會怎樣?
- 同一個 controller 一旦 
abort(),就不能復用;要新建: 
controller.abort();
controller = new AbortController(); // 重新開始fetch會立刻以:
{ name: "AbortError", message: "The operation was aborted." }拒絕(reject)所以務必用 try/catch 或 catch() 正確處理。
兼容性
?? 支持:Chrome 66+、Firefox 57+、Safari 12+、Edge 16+?? 不支持:IE(RIP ??)
別再讓 fetch 為所欲為
AbortController 給了 fetch() 一直缺失的控制力。 無論是搜索、篩選還是各種用戶交互,你都能即時取消無用請求——省時間、省流量、避競態(tài)。
記住這句話:
能跑 ≠ 該跑。















 
 
 









 
 
 
 