AbortController:讓異步操作隨時說停就停

AbortController:讓異步操作隨時說停就停

一、什么是 AbortController?

AbortController 是 JavaScript 在瀏覽器和部分 Node.js 環境中提供的全局類,用來中止正在進行或待完成的異步操作(如 fetch() 請求、事件監聽、可寫流、數據庫事務等)。通過它,我們可以在需要的時候自由地終止這些操作,避免不必要的開銷或冗長的等待。

1. 核心思路

創建一個 AbortController 實例后,可以通過它的 signal 屬性將中止信號傳遞給相應的 API。當調用 controller.abort() 時,所有使用該信號的操作都會收到中止通知,并根據設置的邏輯停止執行或拋出錯誤。

二、基礎用法

// 創建 AbortController 實例
const controller = new AbortController();// 拿到 signal,并可將其傳入需要可中止的 API
const signal = controller.signal;// 主動觸發中止
controller.abort();

1. 實例 signal 屬性

  • signal 是一個 AbortSignal 實例,可被用于任何支持中止的 API(如 fetch()、事件監聽器等)
  • 一旦 abort() 被調用,signal 就會觸發 abort 事件,標記為已中止

2. 實例 abort() 方法

  • 調用后會讓該 signal 上監聽的所有異步操作同時中止
  • 可選地,abort(reason) 可以傳遞一個原因或錯誤,供業務邏輯作更細粒度的處理

3. 監聽中止事件

controller.signal.addEventListener('abort', () => {// 在這里編寫中止后的邏輯,例如清理資源或提示用戶
});

三、實用場景與示例

1. 事件監聽器自動清理

我們可以在添加事件監聽器時將 signal 作為選項的一部分

一旦 abort() 被調用,會自動移除與該 signal 關聯的監聽器,從而簡化了取消事件監聽的流程

const controller = new AbortController();window.addEventListener('resize', () => {console.log('Window resized!');
}, { signal: controller.signal });// 調用 abort(),會自動移除 resize 監聽器
document.getElementById('but').onclick = () => {controller.abort();
}
1.1. 優勢
  • 無需手動保存監聽器引用再調用 removeEventListener()
  • 若有多個監聽器共用同一個 signal,只需一次 abort() 就能一并移除

2. 在 React 中的應用示例

useEffect(() => {const controller = new AbortController();window.addEventListener('resize', handleResize, { signal: controller.signal });window.addEventListener('hashchange', handleHashChange, { signal: controller.signal });window.addEventListener('storage', handleStorageChange, { signal: controller.signal });return () => {// 調用一次 abort(),所有監聽器全部被移除controller.abort();};
}, []);

3. 中止 fetch() 請求

fetch() 支持通過 signal 中止 HTTP 請求,是 AbortController 最常見的應用場景之一

async function uploadFile(file) {const controller = new AbortController();const responsePromise = fetch('/upload', {method: 'POST',body: file,signal: controller.signal,});return { responsePromise, controller };
}const { responsePromise, controller } = uploadFile(file);document.getElementById('but').onclick = () => {controller.abort();
}
  • 一旦 abort 被觸發,fetch() 返回的 Promise 將被拒絕,后端也將收到掛斷請求(具體取決于實際網絡環境)

4. Node.js 中止 http 請求

在新版 Node.js 環境中(v16+),AbortSignal 同樣可以應用于內置的 http 或 https 模塊中,以取消請求或響應讀取。用法與瀏覽器環境基本一致

4.1. server.js
const http = require('http');const server = http.createServer((req, res) => {console.log('收到請求:', req.url);res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });// 模擬長時間響應:每 500ms 輸出一段文字,共輸出 50 次let count = 0;const intervalId = setInterval(() => {if (count < 50) {res.write(`數據塊 #${count}\n`);count++;} else {clearInterval(intervalId);res.end('響應全部完成\n');}}, 500);req.on('close', () => {console.log('客戶端連接關閉,停止發送數據');clearInterval(intervalId);});
});const PORT = 3000;
server.listen(PORT, () => {console.log(`服務器已啟動,監聽端口 ${PORT}`);
});
4.2. controller.js
const http = require('http');function makeAbortableRequest() {const controller = new AbortController();const { signal } = controller;const req = http.get('http://localhost:3000',{ signal },(res) => {console.log('已連接到服務器,響應狀態:', res.statusCode);res.on('data', (chunk) => {console.log('收到數據塊:', chunk.toString());});res.on('end', () => {console.log('響應結束');});});req.on('error', (err) => {console.error('請求錯誤:', err.message || err);});setTimeout(() => {console.log('5 秒時間到,準備中止請求...');controller.abort();}, 5000);
}makeAbortableRequest();

5. 終止流操作

  • 可寫流
    • 對于基于 WritableStream 或者更底層的寫操作,如果支持將 signal 與寫操作關聯,當 abort() 被調用時,即可停止寫入并執行清理
  • 自定義可中止邏輯
    • 在數據庫事務中,自行監聽 signal 的 abort 事件來回滾事務或拋出特定錯誤,都能讓流程變得更靈活
async function example() {const abortController = new AbortController();const stream = new WritableStream({write(chunk, sinkController) {console.log('正在寫入:', chunk);},close() {console.log('寫入完成');},abort(reason) {console.warn('寫操作被中止:', reason);}});const writer = stream.getWriter();let i = 1const inter = setInterval(async () => {await writer.write(`數據塊 ${i}`);i++}, 1000)window.currentAbortController = abortController;window.currentWriter = writer;document.getElementById('cancelButton').onclick = async () => {clearInterval(inter)if (window.currentAbortController && window.currentWriter) {console.log('點擊了取消寫操作按鈕');await window.currentWriter.abort('用戶主動終止寫入');window.currentAbortController.abort('用戶主動終止寫入');} else {console.log('沒有正在進行的寫操作');}};
}example();

四、兼容性

  • 瀏覽器

  • Node.js

Node.js v16 及以上原生支持在 fetch()、http/https 模塊中使用 signal

五、總結與擴展

1. 核心價值

  • AbortController 讓我們可以更優雅地中止異步操作,不再依賴過時的回調或繁瑣的清理邏輯。
  • 避免占用資源或等待無效請求,提升性能和用戶體驗。

2. 應用場景廣泛

  • 事件監聽清理、fetch() 請求取消、Node.js HTTP 請求中止、數據庫事務可回滾……幾乎所有異步操作都能通過一個 signal 實現“一鍵叫停”。

3. 常見注意點

  • 在代碼中使用多條 fetch() 時,務必區分好各自的 controller,或使用 AbortSignal.any() 合并控制。
  • 對于中止錯誤,需要在 .catch() 或事件監聽中顯式處理,防止誤認為是網絡異常或其他錯誤。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75930.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75930.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75930.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

機器學習 從入門到精通 day_04

1. 決策樹-分類 1.1 概念 1. 決策節點 通過條件判斷而進行分支選擇的節點。如&#xff1a;將某個樣本中的屬性值(特征值)與決策節點上的值進行比較&#xff0c;從而判斷它的流向。 2. 葉子節點 沒有子節點的節點&#xff0c;表示最終的決策結果。 3. 決策樹的…

C++ Primer (第五版)-第十三章 拷貝控制

文章目錄 概述13.1拷貝、賦值與銷毀合成拷貝構造函數拷貝初始化參數和返回值拷貝初始化的限制編譯器可以繞過拷貝構造函數拷貝運算符析構函數三/五原則使用default阻止拷貝合成的拷貝控制成員可能是刪除的 private拷貝控制拷貝控制和資源管理行為像值的類類值拷貝賦值運算符定義…

Vue el-from的el-form-item v-for循環表單如何校驗rules(一)

實際業務需求場景&#xff1a; 新增或編輯頁面&#xff08;基礎信息表單&#xff0c;一個數據列表的表單&#xff09;&#xff0c;數據列表里面的表單數是動態添加的。數據可新增、可刪除&#xff0c;在表單保存前&#xff0c;常常需要做表單必填項的校驗&#xff0c;校驗通過以…

測試100問:http和https的區別是什么?

哈嘍&#xff0c;大家好&#xff0c;我是十二&#xff0c;今天給大家分享的問題是&#xff1a;http和https的區別是什么&#xff1f; 首先我們要知道 HTTP 協議傳播的數據都是未加密的&#xff0c;也就是明文的&#xff0c;因此呢使用 http協議傳輸一些隱私信息也就非常不安全&…

YOLOv3超詳細解讀(三):源碼解析:數據處理模塊

一、概述 YOLOv3&#xff08;You Only Look Once v3&#xff09;是一種高效的目標檢測算法&#xff0c;其數據處理模塊是訓練和推理流程的核心部分。本文將深入分析Ultralytics團隊基于PyTorch實現的YOLOv3源碼中的數據處理模塊&#xff0c;重點探討數據加載、預處理和數據增強…

每日算法(雙指針算法)(Day 1)

雙指針算法 1.算法題目&#xff08;移動零&#xff09;2.講解算法原理3.編寫代碼 1.算法題目&#xff08;移動零&#xff09; 2.講解算法原理 數組劃分&#xff0c;數組分塊&#xff08;快排里面最核心的一步&#xff09;只需把0改為tmp 雙指針算法&#xff1a;利用數組下標來…

2025藍橋杯python A組省賽 題解

真捐款去了&#xff0c;好長時間沒練了&#xff0c;感覺腦子和手都不轉悠了。 B F BF BF 賽時都寫假了&#xff0c; G G G 也只寫了爆搜。 題解其實隊友都寫好了&#xff0c;我就粘一下自己的代碼&#xff0c;稍微提點個人的理解水一篇題解 隊友題解 2025藍橋杯C A組省賽 題…

測試基礎筆記第四天(html)

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 html介紹1. 介紹2.骨架標簽3.常用標簽標題標簽段落標簽超鏈接標簽圖片標簽換行和空格標簽布局標簽input標簽&#xff08;變形金剛&#xff09;form標簽列表標簽 htm…

10 穴 汽車連接器的15個設計特點

汽車行業嚴重依賴卓越的電氣系統來確保功能和可靠性。這些系統的關鍵組件是 10 腔連接器&#xff0c;它為布線和信號傳輸提供解決方案。制造商和工程師必須仔細評估這些連接器的設計特性&#xff0c;以優化性能和安全性。 本博客研究了汽車 10 腔連接器的 15 個設計特征&#…

Summary

一、數據結構 1.1 哈希 主要是HashMap和HashSet&#xff1b;其中HashSet底層是一個HashMap屬性。 // 獲取HashMap元素,HashSet均不支持 map.keySet (); // Set<k> map.values (; // Collection<V> map.entrySet();//Set<Map.Entry<K,V>> for (Map.E…

【Leetcode-Hot100】最小覆蓋子串

題目 解答 想到使用雙指針哈希表來實現&#xff0c;雙指針的left和right控制實現可滿足字符串。 class Solution(object):def minWindow(self, s, t):""":type s: str:type t: str:rtype: str"""len_s, len_t len(s), len(t)hash_map {}for…

Flutter 播放利器:`media_kit` 的詳細介紹與使用指南

在 Flutter 項目中實現音視頻播放&#xff0c;開發者過去主要依賴如 video_player、just_audio 等第三方庫&#xff0c;但這些庫或多或少存在一些局限性&#xff0c;比如平臺兼容性差、定制能力不足、播放格式有限等問題。 而 media_kit 是近年崛起的一款全平臺音視頻播放解決…

4.14【Q】pc homework3

我正在學習并行計算&#xff0c;解決這個問題&#xff1f;詳細解釋&#xff0c;越細節越好 我正在學習并行計算&#xff0c;“首次允許在 taskloop 構造中使用 reduction 子句&#xff0c;并引入了 task_reduction&#xff08;用于 taskgroup 構造&#xff09;和 in_reduction&…

ArrayList vs LinkedList,HashMap vs TreeMap:如何選擇最適合的集合類?

精心整理了最新的面試資料和簡歷模板&#xff0c;有需要的可以自行獲取 點擊前往百度網盤獲取 點擊前往夸克網盤獲取 在 Java 開發中&#xff0c;集合類的選擇直接影響程序的性能和代碼的可維護性。不同的數據結構適用于不同的場景&#xff0c;盲目使用可能導致內存浪費、性能…

大模型訓練顯存壓縮實戰:ZeRO-3 vs 梯度累積 vs 量化混合策略

一、顯存瓶頸的本質與挑戰 大模型訓練面臨的核心矛盾是模型參數量指數級增長與GPU顯存容量線性提升之間的鴻溝。以175B參數模型為例&#xff0c;其顯存消耗主要來自三個方面&#xff1a; 參數存儲?&#xff1a;FP32精度下需700GB顯存?梯度緩存?&#xff1a;反向傳播產生的…

邊緣計算與隱私計算的融合:構建數據經濟的“隱形護盾“

在數據成為核心生產要素的今天&#xff0c;邊緣計算與隱私計算的交匯正在重塑技術生態。這并非簡單的技術疊加&#xff0c;而是一場關于數據主權、算力分配與信任機制的深度博弈。本文將從"數據流動的拓撲學"視角&#xff0c;探討二者融合如何重構數字社會的基礎設施…

Obsidian 文件夾體系構建 -INKA

Obsidian 文件夾體系構建 -INKA 本篇文章主要分享一下自己折騰學習實踐過的 INKA 框架方法。原地址&#xff1a;Obsidian文件夾體系構建–INKA。 文章目錄 Obsidian 文件夾體系構建 -INKA前言INKA簡介INKA 理論最佳實踐實際應用 反思 前言 上文 Obsidian文件夾體系構建-ACCES…

ocr-不動產權識別

目錄 一、在阿里云申請ocr識別服務 二、創建springboot項目 三、后續 一、在阿里云申請ocr識別服務 在線體驗&#xff1a;房產證圖片上傳 [阿里官方]不動產權證OCR文字識別_API專區_云市場-阿里云 (aliyun.com) 可以選擇一毛500次這個 當然也可以白嫖100 下面有個在線調試…

LeetCode算法題(Go語言實現)_47

題目 給你一個 m x n 的迷宮矩陣 maze &#xff08;下標從 0 開始&#xff09;&#xff0c;矩陣中有空格子&#xff08;用 ‘.’ 表示&#xff09;和墻&#xff08;用 ‘’ 表示&#xff09;。同時給你迷宮的入口 entrance &#xff0c;用 entrance [entrancerow, entrancecol…

The Strict Teacher (Hard Version) 去除無效的干擾!巧妙轉化

文章目錄 The Strict Teacher (Hard Version) 思考問題&#xff01;那么多個人抓一個人&#xff0c;是否是每一個人都是對于最優策略的答案是有貢獻的&#xff1f;答案是否定的&#xff0c;其實問題可以簡化為三種情況&#xff1a; 所有的老師都在大衛的右邊&#xff0c;…