fetch() 用 AbortSignal 取消,res.json() 也一样吗?

Posted

技术标签:

【中文标题】fetch() 用 AbortSignal 取消,res.json() 也一样吗?【英文标题】:fetch() cancels with an AbortSignal, does res.json() too? 【发布时间】:2022-01-12 13:55:27 【问题描述】:

我了解使用 AbortSignal 取消正在进行的请求的工作流程,即将其传递给选项:

const res = await fetch('/endpoint',  signal );
const data = await res.json();

但是,如果信号在请求本身完成之后被取消,但数据被解析之前会发生什么?像这样:

const res = await fetch('/endpoint',  signal );
// Cancel signal here
const data = await res.json();

My tests 在 Firefox、Chrome 和 Safari 中显示会在res.json() 期间正确取消并抛出,但这是官方行为吗?

const log = (...text) => document.body.insertAdjacenthtml('beforeend', `$text.join(' ')<br />`);

(async () => 
  try 
    const controller = new AbortController();
    const signal = controller.signal;

    const res = await fetch('https://swapi.dev/api/films/2/',  signal );
    log('Request:', signal.aborted);
    controller.abort();
    log('Before:', signal.aborted);
    const data = await res.json();
    log('After:', signal.aborted);
   catch (error) 
    log('Cancelled:', error.name);
  
)();

// Request: false
// Before: true
// Cancelled: AbortError

从输出中我们可以看到它正确地在res.json() 上抛出,它永远不会到达After 步骤,它是用AbortError 抛出的。

【问题讨论】:

【参考方案1】:

是的,这是官方行为。 json()(和朋友)消耗响应的正文。根据https://fetch.spec.whatwg.org/#dom-global-fetch 的第 10 步,该主体可能会因信号而处于中止状态。在这种情况下,json()(和朋友)基本上会重新抛出。

【讨论】:

正是我要找的,虽然硬规范有点难读,但我相信这就是我想要的,谢谢!

以上是关于fetch() 用 AbortSignal 取消,res.json() 也一样吗?的主要内容,如果未能解决你的问题,请参考以下文章

前端进阶使用fetch/axios时, 如何取消http请求

取消设置 mysql_fetch_field 对象值 MYSQL PHP

使用 Fetch api Javascript 取消订阅电子邮件

React Update Fetch on Checkbox Click

reactreact组件销毁中清理异步操作和取消请求

使用fetch进行数据请求时报json错误