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

相关推荐
大怪v39 分钟前
前端佬们!塌房了!用过Element-Plus的进来~
前端·javascript·element
拉不动的猪1 小时前
electron的主进程与渲染进程之间的通信
前端·javascript·面试
鱼樱前端2 小时前
Rollup 在前端工程化中的核心应用解析-重新认识下Rollup
前端·javascript
rookie fish3 小时前
websocket结合promise的通信协议
javascript·python·websocket·网络协议
PsG喵喵3 小时前
用 Pinia 点燃 Vue 3 应用:状态管理革新之旅
前端·javascript·vue.js
鹏仔工作室3 小时前
vue h5实现车牌号输入框
前端·javascript·vue.js
冴羽3 小时前
SvelteKit 最新中文文档教程(11)—— 部署 Netlify 和 Vercel
前端·javascript·svelte
海晨忆3 小时前
JS—ES5与ES6:2分钟掌握ES5与ES6的区别
开发语言·javascript·es6·es5与es6的区别
DT——3 小时前
Vue2和Vue3的区别
开发语言·javascript·vue.js
cliff,4 小时前
JavaScript基础巩固之小游戏练习
javascript·笔记·学习