首页 > 解决方案 > 在浏览器中使用 JavaScript 读取带有 for-await 的流

问题描述

我正在使用以下代码在浏览器中使用fetch带有进度指示的用户手势下载大型内容:

const url = 'https://source.unsplash.com/random';
const response = await fetch(url);
const total = Number(response.headers.get('content-length'));
let loaded = 0;
const reader = response.body.getReader();
let result;
while (!(result = await reader.read()).done) {
  loaded += result.value.length;
  // Display loaded/total in the UI
}

我在一个相关问题中看到了一个片段,这让我相信这可以简化为:

const url = 'https://source.unsplash.com/random';
const response = await fetch(url);
const total = Number(response.headers.get('content-length'));
let loaded = 0;
for await (const result of response.body.getReader()) {
  loaded += result.value.length;
  // Display loaded/total in the UI
}

getReader返回一个ReadableStreamDefaultReader来自Streams API的 a,它是一个 Web API 以及一个 Node API,这使得仅查找与 Web 相关的信息非常困难。

在上面的代码片段中,代码失败了response.body.getReader(...) is not a function 或者它的返回值不是 async iterable。我检查了对象原型,确实我认为它没有Symbol.asyncIterator,所以是的,难怪浏览器无法迭代它。

所以那个问题中的代码一定是错误的,但现在我想知道,没有办法获取这样的流并使用 迭代它for-await?我想您需要将其包装在异步生成器中并以与第一个片段类似的方式产生块,对吗?

是否有现有的或计划中的 API 可以使这更加简化,更接近第二个片段,但实际上可以工作?

标签: javascript

解决方案


ReadableStream 本身实现了一个异步迭代

 for await (const result of response.body) {
   loaded += result.value.length;
   // Display loaded/total in the UI
 }

推荐阅读