AJAX vs Fetch:进度监控与返回数据监控的深度对比

在Web开发中,异步请求是前端与后端交互的核心方式,而AJAX和Fetch作为两大主流方案,在进度监控和返回数据监控方面有着显著差异。本文将从技术原理、代码实现到实际应用场景,为你深度解析两者的区别及选型策略。

一、进度监控:AJAX的天然优势 vs Fetch的曲线救国

1. AJAX的进度监控

AJAX基于XMLHttpRequest对象,通过**onprogress事件**直接实现进度监控,代码简洁直观:

javascript 复制代码
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/large-file');

// 监控下载进度
xhr.onprogress = (event) => {
  if (event.lengthComputable) {
    const percent = (event.loaded / event.total) * 100;
    console.log(`下载进度: ${percent.toFixed(1)}%`);
  }
};

xhr.onload = () => {
  if (xhr.status === 200) {
    console.log('下载完成,数据长度:', xhr.responseText.length);
  }
};
xhr.send();

优势

  • 原生支持:无需额外处理,直接通过事件监听进度。
  • 双向监控 :同时支持上传(xhr.upload.onprogress)和下载进度。
  • 兼容性佳:兼容至IE7,适合需要广泛浏览器支持的场景。

2. Fetch的进度监控

Fetch基于Promise,原生不支持进度监控 ,需通过ReadableStream间接实现:

javascript 复制代码
async function fetchWithProgress(url, onProgress) {
  const response = await fetch(url);
  const total = parseInt(response.headers.get('Content-Length') || 0);
  let loaded = 0;
  const reader = response.body.getReader();

  const stream = new ReadableStream({
    start(controller) {
      function read() {
        reader.read().then(({ done, value }) => {
          if (done) {
            controller.close();
            return;
          }
          loaded += value.length;
          onProgress(loaded, total); // 触发进度回调
          controller.enqueue(value);
          read(); // 继续读取下一块数据
        });
      }
      read();
    }
  });

  return new Response(stream, { headers: response.headers });
}

// 使用示例
fetchWithProgress('https://example.com/large-file', (loaded, total) => {
  console.log(`下载进度: ${Math.round((loaded / total) * 100)}%`);
}).then(response => response.blob());

局限性

  • 代码复杂:需手动处理流数据,逻辑繁琐。
  • 仅支持下载 :上传进度需切换回XMLHttpRequest
  • 兼容性差 :IE不支持ReadableStream,需现代浏览器。

二、返回数据监控:AJAX的实时性 vs Fetch的流式处理

1. AJAX的返回数据监控

AJAX通过onreadystatechange事件监听响应状态,实时获取数据:

javascript 复制代码
xhr.onreadystatechange = () => {
  if (xhr.readyState === 3) { // 数据接收中
    console.log('已接收数据:', xhr.responseText.length);
  } else if (xhr.readyState === 4) { // 请求完成
    if (xhr.status === 200) {
      console.log('完整数据:', xhr.responseText);
    }
  }
};

特点

  • 实时性强:可在数据接收过程中逐步处理(如分页渲染)。
  • 内存友好:避免一次性加载大文件导致内存压力。

2. Fetch的返回数据监控

Fetch通过Response对象获取数据,但默认一次性加载全部内容:

javascript 复制代码
fetch('https://example.com/large-file')
  .then(response => {
    const reader = response.body.getReader();
    const contentLength = parseInt(response.headers.get('Content-Length'));
    let received = 0;

    return new ReadableStream({
      start(controller) {
        function read() {
          reader.read().then(({ done, value }) => {
            if (done) {
              controller.close();
              return;
            }
            received += value.length;
            console.log(`已接收: ${received}/${contentLength} bytes`);
            controller.enqueue(value);
            read();
          });
        }
        read();
      }
    });
  })
  .then(stream => {
    // 处理流式数据(如分块渲染)
  });

特点

  • 流式处理:适合大文件或实时数据流,分块处理降低内存占用。
  • 代码侵入性:需手动管理流,增加复杂度。

三、选型策略:根据项目需求抉择

场景 推荐方案 理由
需简单进度监控 AJAX 原生支持,代码简洁,兼容性好。
需流式处理大文件 Fetch 支持ReadableStream,分块处理内存高效(但需自行实现进度逻辑)。
需现代浏览器特性 Fetch 语法简洁,结合async/await提升可读性(牺牲部分兼容性)。
需上传进度监控 XMLHttpRequest Fetch无原生支持,需混合使用两种API。

四、总结:没有银弹,只有权衡

AJAX和Fetch在进度监控和返回数据监控上各有优劣:

  • AJAX:适合传统项目或对兼容性要求高的场景,进度监控开箱即用。
  • Fetch:适合现代Web应用或需流式处理的场景,但需自行处理进度逻辑。

实际开发中,可结合两者优势(如用Fetch发送请求,用XMLHttpRequest监控上传进度),根据具体需求灵活选型。

相关推荐
FansUnion4 分钟前
用 AI 自动生成壁纸标题、描述和 SEO Slug
javascript
大雨还洅下17 分钟前
前端 JS: async, await; Generator
javascript
juejin_cn18 分钟前
[转][译] 从零开始构建 OpenClaw — 第三部分(元技能)
javascript
颜酱3 小时前
二叉树分解问题思路解题模式
javascript·后端·算法
炫饭第一名3 小时前
速通Canvas指北🦮——路径与形状篇
前端·javascript·程序员
无责任此方_修行中4 小时前
如何利用 pnpm 的安全控制功能防御 npm 供应链攻击
javascript·npm·node.js
进击的尘埃4 小时前
前端状态管理的本质:从 Vuex 到 Pinia,我们到底在管理什么?
javascript
码路飞4 小时前
GPT-5.3 Instant 终于学会好好说话了,顺手对比了下同天发布的 Gemini 3.1 Flash-Lite
java·javascript
Lee川4 小时前
从回调地狱到同步之美:JavaScript异步编程的演进之路
javascript·面试
进击的尘埃4 小时前
WebSocket 长连接方案设计:从心跳保活到断线重连的生产级实践
javascript