Fetch可以做请求的进度监控吗?

 先自问自答:fetch 原生做不到请求的进度监控。fetch 是基于 Promise 的,在Promise的世界里,它的结果只有成功或者失败,没有说成功了百分之几或者失败了百分之几的说法。

如果使用Fetch想实现进度监控功能,可能需要结合使用ReadableStreamTransformStream等Web Streams API,或者考虑使用第三方库来辅助实现。

一、简单实现进度监控

我们在发送请求之前,使用如FormDataBlob等对象来包装文件或数据,并通过监听这些对象在发送过程中的变化来间接获取上传进度。但这种方法并不直接由fetch API 提供,实现起来较为复杂。

这里我们使用一个较新的API来试试。ReadableStream 支持流式处理数据,可以逐块读取数据,我们可以用它来实现一个文件流的进度。
ReadableStream

      // fetch请求进度监控
      async function fetchWithProgress(url, onProgress) {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`请求异常: ${response.status}`);
        }

        const reader = response.body.getReader();
        let totalBytesReceived = 0;

        const contentLength = parseInt(
          response.headers.get("content-length") || 0
        );

        return new ReadableStream({
          start(controller) {
            function push() {
              reader.read().then(({ done, value }) => {
                if (done) {
                  controller.close();
                  return;
                }
                totalBytesReceived += value.length;
                onProgress(totalBytesReceived, contentLength);
                controller.enqueue(value);
                push();
              });
            }
            push();
          },
        });
      }

      // 示例
      fetchWithProgress("https://example.com/large-file", (loaded, total) => {
        console.log(
          `下载进度: ${Math.round((loaded / total) * 100)}%`
        );
      }).then((stream) => {
        // 处理stream
        const writer = new WritableStream({
          write(chunk) {
            // 处理chunk
            console.log(`接受chunk大小: ${chunk.length} bytes`);
          },
        });

        stream.pipeTo(writer);
      });

二、使用第三方库实现进度监控

  1. axios
import axios from 'axios';

axios.request({
    method: 'GET',
    url: 'http://localhost:3000/file',
    responseType: 'stream',
    onDownloadProgress: function(progressEvent) {
        const percentCompleted = Math.round((progressEvent.loaded / progressEvent.total) * 100);
        console.log(`下载进度: ${percentCompleted}%`);
    }
}).then(response => {
    // 处理响应
});
  1. fetch-progress
import fetchProgress from 'fetch-progress';

fetchProgress('http://localhost:3000/file', (progress) => {
    console.log(`下载进度: ${progress.percent}%`);
}).then(response => {
    // 处理响应
});

三、XHR的进度监控

如果不严格要求使用fetch API,可以考虑使用XMLHttpRequest,它原生支持上传和下载的进度事件,可以直接使用XMLHttpRequest对象的onprogress事件来跟踪上传进度。

      // fetch请求进度监控
      function downloadWithProgress(url, onProgress) {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", url, true);
        xhr.responseType = "blob";

        // 监听下载进度
        xhr.onprogress = function (event) {
          if (event.lengthComputable) {
            const percentComplete = Math.round(
              (event.loaded / event.total) * 100
            );
            onProgress(percentComplete);
          }
        };

        // 监听加载完成
        xhr.onload = function () {
          if (xhr.status === 200) {
            console.log("下载完成!");
          } else {
            console.error("下载异常:", xhr.status);
            throw new Error(`下载异常: ${xhr.status}`);
          }
        };

        // 监听错误
        xhr.onerror = function () {
          console.error("请求错误!");
          throw new Error("请求错误!");
        };

        // 监听超时
        xhr.ontimeout = function () {
          console.error("请求超时!");
          throw new Error("请求超时!");
        };

        // 发送请求
        xhr.send();
      }

      // 示例用法
      downloadWithProgress("http://localhost:3000/file", (progress) => {
        console.log(`下载进度: ${progress}%`);
      });

 总结:如果需要做请求的进度监控,在没有强制一点要使用Fetch的情况下,还是老老实实使用XHR吧,或者使用成熟的第三方请求库,比如axios等,它该有的功能都有了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值