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监控上传进度),根据具体需求灵活选型。

相关推荐
像风一样自由20206 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
浪裡遊7 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
Liudef068 小时前
2048小游戏实现
javascript·css·css3
独立开阀者_FwtCoder10 小时前
【Augment】 Augment技巧之 Rewrite Prompt(重写提示) 有神奇的魔法
前端·javascript·github
我想说一句10 小时前
事件机制与委托:从冒泡捕获到高效编程的奇妙之旅
前端·javascript
汤姆Tom11 小时前
JavaScript reduce()函数详解
javascript
小飞悟11 小时前
你以为 React 的事件很简单?错了,它暗藏玄机!
前端·javascript·面试
中微子11 小时前
JavaScript 事件机制:捕获、冒泡与事件委托详解
前端·javascript
蓝翔认证10级掘手11 小时前
🤯 家人们谁懂啊!我的摸鱼脚本它...它成精了!🚀
javascript
前端康师傅12 小时前
JavaScript 中你不知道的按位运算
前端·javascript