惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
博客园_首页
M
MIT News - Artificial intelligence
雷峰网
雷峰网
GbyAI
GbyAI
博客园 - 叶小钗
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
V2EX
S
SegmentFault 最新的问题
H
Help Net Security
Apple Machine Learning Research
Apple Machine Learning Research
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 【当耐特】
V
Visual Studio Blog
月光博客
月光博客
G
Google Developers Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
云风的 BLOG
云风的 BLOG
美团技术团队
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
有赞技术团队
有赞技术团队

Surmon.me

一人有限集团 你就是不敢 创造力是温柔的谎言 人类正在退出人类 AI 代替不了这样的你 脉冲点火背后的架构设计 基于 Cloudflare 生态的 AI Agent 实现 NodePress 支持用户登录了 从统计学习到通用智能 2025 投资报告:走慢的路 无依之地 会杀人的菩萨 无我不是共识 文化的积重与偏见 当下即安 科学的尽头是态度 无我不是 Egoless 信仰不因恐惧而存在 世间无解的矛与盾 先别急着做些什么 佛不需要你的皈依 真理的幻觉 两扇大门 造心里的浮屠 自胜者强 逻辑与智慧 真的相 快乐的秘密 只需愿意 是名体验
给 fetch 加一套可退化的中止方案
Surmon · 2018-12-06 · via Surmon.me

原创

Fetch 弱于 XHR 的致命一点是没有 abort 机制,但我们有 hack 方案。

AbortController

AbortController 目前还是一个实验特性的 API, 官方释义为:中止一个尚未完成的 DOM 请求。这能够中止 fetch 请求,任何响应 Body 的消费者和流。

AbortSignal 用以绑定控制器实例与对应流的关系,并进行通信,AbortController.abort 用以终止绑定的流(向 AbortSignal 发出终止信号)。

code:

        
        

12345678910111213141516

const controller = new AbortController() const signal = controller.signal function fetchVideo() { fetch('https://www.quirksmode.org/html5/videos/big_buck_bunny.mp4', { signal }) .then(res => { console.log('res', res) }) .catch(err => { console.warn('err', err) // DOMException: The user aborted a request. }) } fetchVideo() controller.abort() console.log('Download aborted')

AbortController polyfill

Gtihub: abortcontroller-polyfill

  1. 模拟 AbortSignal、AbortController 构造对象,AbortSignal 采用原生 Event 对象派发 abort 事件信号
  2. 包装 nativeFetch,识别次参 init 参数中的 AbortSignal 实例,如果包含 signal,则绑定事件监听,当 signal 发出 abort 信号时,主动 Reject Promise

结构图:

点:核心采用 Event 和 addEventListener 进行通信,用 Promise.race 竟态任务维护结果的时序和唯一性。

内部队列

  1. 包装 Fetch,扩展 abort 方法
  2. 内部维护请求状态,存储请求状态及数据
  3. 执行 abort 会改变状态,直到真正的 Resove/Reject 发生时,判断 abort 状态来决定要不要操作,或操作 reject('Abort Error'), 但不可以真正取消 Fetch,Promise 也可能会永远处于无响应状态

结构图:

缺陷是当你 abort 之后,你的 Promise 可能永远不会有响应,而且不会被释放...

  1. abort -> abort(Fetch)
  2. abort -> Promise.race[Promise.reject(), fetch()]
  3. (abort -> aborted) ? Promise.reject() : fetch()

这不是取消 Promise 的问题,而是终止 Fetch 终止 HTTP 的问题,除了原生的 AbortController,不会有更优秀的办法可以做到。

完了。