TS2504:类型“ReadableStream<Uint8Array>”必须具有返回异步迭代器的“[Symbol.asyncIterator]()”方法

ari*_*nmz 6 fetch typescript reactjs

我正在尝试在新的 CRA React 应用程序中使用获取响应的主体作为异步迭代。

const response = await fetch('example.com');

if (response.ok && response.body) {
  for await (const b of response.body) {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

根据 MDN应该可以:

Response 接口的主体只读属性是主体内容的 ReadableStream。

和:

ReadableStream 实现了异步可迭代协议。这可以使用 for wait...of 语法对流中的块进行异步迭代:

我已经根据这个答案将目标设置为 tsconfig.json 中的 esnext ,但我仍然收到错误。

Bra*_*eld 5

首先请注意,在浏览器中,只有 Firefox 实际上在 ReadableStream 上实现了异步迭代,如兼容性表中所列

因此,官方类型不包含该方法。

如果在节点中运行,则可以使用替代方案,并且可以从此处获得浏览器polyfill

如果代码仅在 Nodejs 中运行,则直接进行类型转换:

import { default as stream } from 'node:stream'.
import type { ReadableStream } from 'node:stream/web'.

const response = await fetch('xxx')
stream.Readable.fromWeb(response.body as ReadableStream<Uint8Array>)
Run Code Online (Sandbox Code Playgroud)

如果代码需要考虑浏览器的运行环境,可以添加一个polyfill:

ReadableStream.prototype[Symbol.asyncIterator] = async function* () {
  const reader = this.getReader()
  try {
    while (true) {
      const {done, value} = await reader.read()
      if (done) return
      yield value
    }
  }
  finally {
    reader.releaseLock()
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您只是在实现该功能的浏览器中运行,添加此功能会让编译器满意

interface ReadableStream<R = any> {
    [Symbol.asyncIterator](): AsyncIterableIterator<R>;
}
Run Code Online (Sandbox Code Playgroud)