fetch() 使用 AbortSignal 取消,res.json() 也是吗?

fetch() cancels with an AbortSignal, does res.json() too?

我了解使用 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.

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