fetch如何手动实现支持超时机制和进度机制

要在 fetch API 中手动实现超时机制和进度机制,可以结合使用 AbortControllerReadableStream。以下是详细的实现步骤:

实现超时机制

使用 AbortController 来实现超时机制。AbortController 可以用于中止一个 fetch 请求。

实现进度机制

使用 ReadableStream 来实现进度机制。通过读取响应流并计算已加载的数据量,可以实现进度更新。

完整示例

以下是一个完整的示例,展示如何在 fetch 中手动实现超时机制和进度机制:

async function fetchWithTimeoutAndProgress(url, options = {}, timeout = 5000, onProgress) {
  const controller = new AbortController();
  const { signal } = controller;
  const fetchOptions = { ...options, signal };

  // 设置超时
  const timeoutId = setTimeout(() => controller.abort(), timeout);

  try {
    const response = await fetch(url, fetchOptions);
    clearTimeout(timeoutId);

    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }

    const contentLength = response.headers.get('content-length');
    if (!contentLength) {
      throw new Error('Content-Length response header unavailable');
    }

    const total = parseInt(contentLength, 10);
    let loaded = 0;

    const reader = response.body.getReader();
    const stream = new ReadableStream({
      start(controller) {
        function push() {
          reader.read().then(({ done, value }) => {
            if (done) {
              controller.close();
              return;
            }
            loaded += value.byteLength;
            onProgress((loaded / total) * 100);
            controller.enqueue(value);
            push();
          }).catch(error => {
            console.error('Stream error:', error);
            controller.error(error);
          });
        }
        push();
      }
    });

    const newResponse = new Response(stream);
    return newResponse.text();
  } catch (error) {
    clearTimeout(timeoutId);
    if (error.name === 'AbortError') {
      throw new Error('Request timed out');
    }
    throw error;
  }
}

// 使用示例
fetchWithTimeoutAndProgress(
  'https://jsonplaceholder.typicode.com/posts',
  {},
  5000,
  (progress) => {
    console.log(`Progress: ${progress}%`);
  }
)
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

解释

  1. 超时机制:
    • 使用 AbortController 创建一个控制器,并将其信号传递给 fetch 请求。
    • 使用 setTimeout 在指定时间后调用 controller.abort() 来中止请求。
    • 在请求完成或发生错误时,使用 clearTimeout 清除超时。
  2. 进度机制:
    • 获取响应的 content-length 头信息来确定总数据大小。
    • 使用 ReadableStream 和 response.body.getReader() 读取响应流。
    • 在读取过程中,计算已加载的数据量,并调用 onProgress 回调函数更新进度。

注意事项

  • 错误处理:确保在捕获错误时清除超时,并处理 AbortError。
  • 浏览器兼容性:ReadableStream 和 AbortController 是现代浏览器的特性,确保你的目标浏览器支持这些特性。

通过这种方式,你可以在使用 fetch 时手动实现超时和进度机制,提供更好的用户体验和控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值