JavaScript教程:使用Fetch API追踪下载进度

JavaScript教程:使用Fetch API追踪下载进度

ru.javascript.info Современный учебник JavaScript ru.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ru/ru.javascript.info

理解Fetch API的进度追踪机制

在现代Web开发中,Fetch API已成为发起网络请求的主流方式。它不仅提供了简洁的语法,还支持对下载过程的实时监控。本文将深入探讨如何利用Fetch API追踪文件下载进度。

为什么需要进度追踪?

当处理大文件下载时,用户界面显示进度条可以显著提升用户体验。传统的response.json()response.text()方法会一次性返回所有数据,无法提供中间状态。这时就需要使用更底层的response.body特性。

核心概念:ReadableStream

response.body返回的是一个ReadableStream对象,这是Streams API规范中定义的一种特殊数据类型。它允许我们按块(chunk)逐步读取响应体,而不是等待整个响应完成。

实现进度追踪的步骤

1. 获取流读取器

const reader = response.body.getReader();

这行代码创建了一个流读取器,它是我们读取数据块的关键。

2. 循环读取数据块

while(true) {
  const {done, value} = await reader.read();
  if (done) break;
  // 处理value
}

每次调用reader.read()都会返回:

  • done:布尔值,表示是否读取完成
  • value:包含数据块的Uint8Array类型数组

3. 计算和显示进度

通过累加每个数据块的长度,我们可以计算已下载的字节数:

let receivedLength = 0;
const contentLength = +response.headers.get('Content-Length');

while(true) {
  const {done, value} = await reader.read();
  if (done) break;
  
  receivedLength += value.length;
  console.log(`已下载: ${receivedLength}/${contentLength}字节`);
}

完整示例解析

让我们看一个完整的实现示例:

async function trackDownloadProgress() {
  // 1. 发起请求并获取流读取器
  const response = await fetch('large-file-url');
  const reader = response.body.getReader();
  
  // 2. 获取总长度
  const contentLength = +response.headers.get('Content-Length');
  let receivedLength = 0;
  let chunks = [];
  
  // 3. 读取数据块
  while(true) {
    const {done, value} = await reader.read();
    if (done) break;
    
    chunks.push(value);
    receivedLength += value.length;
    updateProgressBar(receivedLength, contentLength);
  }
  
  // 4. 合并数据块
  const chunksAll = new Uint8Array(receivedLength);
  let position = 0;
  for(let chunk of chunks) {
    chunksAll.set(chunk, position);
    position += chunk.length;
  }
  
  // 5. 解码数据
  const result = new TextDecoder("utf-8").decode(chunksAll);
  return JSON.parse(result);
}

function updateProgressBar(received, total) {
  const percent = Math.round((received / total) * 100);
  console.log(`下载进度: ${percent}%`);
}

关键注意事项

  1. 内容长度可能不可用Content-Length头部在某些情况下可能不存在,特别是跨域请求时。

  2. 二进制数据处理:如果需要处理二进制数据而非文本,可以直接创建Blob对象:

    const blob = new Blob(chunks);
    
  3. 性能考虑:对于超大文件,频繁更新UI可能影响性能,可以考虑节流(throttle)进度更新。

  4. 错误处理:务必添加适当的错误处理逻辑,包括网络错误和流读取错误。

与XMLHttpRequest的对比

虽然XMLHttpRequest也支持进度追踪,但Fetch API提供了更现代的Promise-based接口和更灵活的流处理能力。不过需要注意的是,Fetch API目前不支持上传进度追踪,这方面仍需使用XMLHttpRequest。

实际应用场景

  1. 大文件下载进度显示
  2. 实时数据处理(如视频流)
  3. 内存敏感型应用(可以分块处理数据而不需要一次性加载全部内容)

掌握Fetch API的进度追踪技术,能够显著提升处理大型网络请求的能力,为用户提供更流畅的体验。

ru.javascript.info Современный учебник JavaScript ru.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ru/ru.javascript.info

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潘聪争

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值