【Web API系列】XMLHttpRequest API和Fetch API深入理解与应用指南

在这里插入图片描述


前言

在现代Web开发中,客户端与服务器之间的异步通信是构建动态应用的核心能力。无论是传统的AJAX技术(基于XMLHttpRequest)还是现代的Fetch API,它们都为实现这一目标提供了关键支持。本文将从底层原理、核心功能、代码实践到实际应用场景,系统性地对比和分析这两种API的异同,帮助你掌握如何在不同场景下选择最佳解决方案。


文章目录

  • 前言
  • 一、XMLHttpRequest API:传统异步请求的基石
    • 1.1 核心概念与工作原理
    • 1.2 关键功能与高级用法
    • 1.3 局限性分析
  • 二、Fetch API:现代Web请求的标准方案
    • 2.1 设计理念与核心优势
    • 2.2 基础用法与代码示例
    • 2.3 高级功能实践
    • 2.4 常见问题与解决方案
  • 三、XMLHttpRequest与Fetch API的深度对比
    • 3.1 功能特性对比
    • 3.2 性能与适用场景
  • 四、实战案例:构建一个健壮的HTTP客户端
    • 4.1 基于Fetch的封装库
    • 4.2 实现文件分片上传
  • 总结


一、XMLHttpRequest API:传统异步请求的基石

1.1 核心概念与工作原理

XMLHttpRequest(XHR)是浏览器提供的原生API,用于在不刷新页面的情况下与服务器交换数据。其核心流程包括:

  1. 实例化对象:通过构造函数创建XMLHttpRequest实例。
  2. 配置请求:指定HTTP方法、URL及是否异步。
  3. 绑定事件:监听请求状态变化(如onloadonerror)。
  4. 发送请求:调用send()方法并处理响应数据。
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onload = function() {if (xhr.status === 200) {console.log(JSON.parse(xhr.responseText));} else {console.error('请求失败:', xhr.status);}
};
xhr.onerror = function() {console.error('网络错误');
};
xhr.send();

1.2 关键功能与高级用法

  • 同步与异步模式

    // 同步请求(阻塞主线程,不推荐)
    xhr.open('GET', 'https://api.example.com/data', false);
    xhr.send();
    console.log(xhr.responseText);
    
  • 处理二进制数据

    xhr.responseType = 'arraybuffer';
    xhr.onload = function() {const buffer = xhr.response;// 处理二进制数据(如图像或文件)
    };
    
  • 上传进度监控

    xhr.upload.onprogress = function(event) {const percent = (event.loaded / event.total) * 100;console.log(`上传进度: ${percent}%`);
    };
    
  • 超时控制

    xhr.timeout = 5000; // 5秒超时
    xhr.ontimeout = function() {console.error('请求超时');
    };
    

1.3 局限性分析

  1. 回调地狱:事件监听机制导致代码嵌套复杂。
  2. 错误处理不统一:需手动检查HTTP状态码和网络错误。
  3. 不支持Promise:与现代异步编程模式不兼容。

二、Fetch API:现代Web请求的标准方案

2.1 设计理念与核心优势

Fetch API基于Promise设计,提供更简洁、灵活的请求方式,并天然支持以下特性:

  • 链式调用:避免回调嵌套。
  • Streams API集成:处理流式数据(如大文件下载)。
  • CORS与安全策略:默认不发送跨域Cookie,需显式配置。

2.2 基础用法与代码示例

fetch('https://api.example.com/data').then(response => {if (!response.ok) throw new Error('HTTP错误');return response.json();}).then(data => console.log(data)).catch(error => console.error('请求失败:', error));

2.3 高级功能实践

  • 自定义请求头与模式

    fetch('https://api.example.com/data', {method: 'POST',headers: {'Content-Type': 'application/json','Authorization': 'Bearer token'},body: JSON.stringify({ key: 'value' }),mode: 'cors', // 跨域模式credentials: 'include' // 包含Cookie
    });
    
  • 中断请求(AbortController)

    const controller = new AbortController();
    setTimeout(() => controller.abort(), 5000);fetch('https://api.example.com/data', {signal: controller.signal
    }).catch(error => {if (error.name === 'AbortError') {console.log('请求被手动取消');}
    });
    
  • 流式数据处理

    fetch('https://api.example.com/large-file').then(response => {const reader = response.body.getReader();return new ReadableStream({start(controller) {function push() {reader.read().then(({ done, value }) => {if (done) {controller.close();return;}controller.enqueue(value);push();});}push();}});}).then(stream => new Response(stream)).then(response => response.blob());
    

2.4 常见问题与解决方案

  • 错误处理优化

    async function fetchWithRetry(url, retries = 3) {for (let i = 0; i < retries; i++) {try {const response = await fetch(url);if (!response.ok) throw new Error('HTTP错误');return await response.json();} catch (error) {if (i === retries - 1) throw error;await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));}}
    }
    
  • 超时封装

    function fetchWithTimeout(url, timeout = 5000) {return Promise.race([fetch(url),new Promise((_, reject) =>setTimeout(() => reject(new Error('请求超时')), timeout))]);
    }
    

三、XMLHttpRequest与Fetch API的深度对比

3.1 功能特性对比

特性XMLHttpRequestFetch API
Promise支持
请求取消是(abort())是(AbortController)
流式数据处理有限支持完全支持
CORS处理需手动配置默认安全策略
Service Worker不支持完全集成

3.2 性能与适用场景

  • XMLHttpRequest适用场景

    • 需要监控上传/下载进度。
    • 兼容旧版浏览器(如IE10及以下)。
  • Fetch API推荐场景

    • 现代Web应用开发。
    • 需要与Service Worker配合实现离线缓存。
    • 处理流式数据或大文件。

四、实战案例:构建一个健壮的HTTP客户端

4.1 基于Fetch的封装库

class HttpClient {constructor(baseURL, headers = {}) {this.baseURL = baseURL;this.headers = headers;}async request(endpoint, options = {}) {const url = `${this.baseURL}${endpoint}`;const response = await fetch(url, {...options,headers: { ...this.headers, ...options.headers }});if (!response.ok) {const error = new Error(`HTTP ${response.status}`);error.response = response;throw error;}const contentType = response.headers.get('content-type');if (contentType?.includes('application/json')) {return response.json();}return response.text();}get(endpoint, params) {const query = new URLSearchParams(params).toString();return this.request(`${endpoint}?${query}`, { method: 'GET' });}post(endpoint, body) {return this.request(endpoint, {method: 'POST',body: JSON.stringify(body),headers: { 'Content-Type': 'application/json' }});}
}// 使用示例
const api = new HttpClient('https://api.example.com', {Authorization: 'Bearer token'
});
api.get('/users', { page: 1 }).then(users => console.log(users));

4.2 实现文件分片上传

async function uploadFile(file, chunkSize = 1024 * 1024) {const totalChunks = Math.ceil(file.size / chunkSize);for (let i = 0; i < totalChunks; i++) {const start = i * chunkSize;const end = Math.min(start + chunkSize, file.size);const chunk = file.slice(start, end);const formData = new FormData();formData.append('file', chunk);formData.append('chunkIndex', i);formData.append('totalChunks', totalChunks);await fetch('/upload', {method: 'POST',body: formData});}
}

总结

XMLHttpRequest作为Web异步通信的奠基者,至今仍在特定场景下发挥作用,而Fetch API凭借其现代化的设计正在成为主流选择。开发者需要根据以下因素决策:

  1. 浏览器兼容性:如需支持旧版浏览器,XHR仍是必要选项。
  2. 功能需求:进度监控、请求取消等特性可能影响技术选型。
  3. 代码可维护性:Fetch的Promise链与async/await语法更易维护。

未来,随着Web Streams API和Service Worker的普及,Fetch API将在性能优化和离线体验领域展现更大潜力。建议在新项目中优先采用Fetch,同时保持对XHR原理的理解以应对遗留系统维护需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/76477.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[特殊字符] Spring Boot 日志系统入门博客大纲(适合初学者)

一、前言 &#x1f4cc; 为什么日志在项目中如此重要&#xff1f; 在开发和维护一个后端系统时&#xff0c;日志就像程序运行时的“黑匣子”&#xff0c;帮我们记录系统的各种行为和异常。一份良好的日志&#xff0c;不仅能帮助我们快速定位问题&#xff0c;还能在以下场景中…

IP协议之IP,ICMP协议

1.因特网中的主要协议是TCP/IP&#xff0c;Interneet协议也叫TCP/IP协议簇 2.ip地址用点分十进制表示&#xff0c;由32位的二进制表示&#xff0c;两部分组成&#xff1a;网络标识主机标识 3.IP地址分类; A:0.0.0.0-127.255.255.255 B&#xff1a;128.0.0.0-191.255.255.25…

GPIO_ReadInputData和GPIO_ReadInputDataBit区别

目录 1、GPIO_ReadInputData: 2、GPIO_ReadInputDataBit: 总结 GPIO_ReadInputData 和 GPIO_ReadInputDataBit 是两个函数&#xff0c;通常用于读取微控制器GPIO&#xff08;通用输入输出&#xff09;引脚的输入状态&#xff0c;特别是在STM32系列微控制器中。它们之间的主要…

洛古B4158 [BCSP-X 2024 12 月小学高年级组] 质数补全(线性筛/dfs)

B4158 [BCSP-X 2024 12 月小学高年级组] 质数补全 - 洛谷 思路1:线性筛,字符串匹配,枚举 质数筛选 要解决这个问题&#xff0c;首先得找出指定范围内&#xff08;这里是 1 到 10000000&#xff09;的所有质数。常用的质数筛选算法有埃拉托斯特尼筛法&#xff08;埃氏筛&#…

一周学会Pandas2 Python数据处理与分析-Pandas2读取Excel

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili Excel格式文件是办公使用和处理最多的文件格式之一&#xff0c;相比CSV文件&#xff0c;Excel是有样式的。Pandas2提…

NVIDIA H100 vs A100:新一代GPU架构性能对比分析

一、核心架构演进对比 ‌Ampere架构&#xff08;A100&#xff09;‌采用台积电7nm工艺&#xff0c;集成540亿晶体管&#xff0c;配备6,912个CUDA核心和432个第三代Tensor Core&#xff0c;支持FP16、TF32和INT8精度计算。其显存子系统采用HBM2e技术&#xff0c;80GB版本带宽可…

保护PCBA的不同方法:喷三防漆 vs 镀膜

PCBA&#xff08;印刷电路板组件&#xff09;的防护工艺中&#xff0c;喷三防漆和镀膜&#xff08;如Parylene气相沉积&#xff09;是两种常见技 术。它们在防护目的上类似&#xff0c;但在具体实现方式和应用场景上有显著差异。以下从外观、工艺、性 能、物理性质和成本五个…

VitePress 项目部署 cloudflare page 提示 npm run build 错误

构建的错误信息如下&#xff1a; 09:52:57.975 ➤ YN0000: Done with warnings in 3s 120ms 09:52:58.072 Executing user command: npm run build 09:52:58.817 npm ERR! Missing script: "build" 09:52:58.818 npm ERR! 09:52:58.818 npm ERR! To see a list of …

C++学习之ORACLE③

1.集合运算符 查询部门号是10和20的员工信息&#xff1a; &#xff1f;思考有几种方式解决该问题 &#xff1f; SQL> select * from emp where deptno in(10, 20) SQL> select * from emp where deptno10 or deptno20 集合运算&#xff1a; Select * from emp …

人工智能之数学基础:复矩阵

本文重点 复矩阵是线性代数中以复数为元素的矩阵,是实矩阵在复数域上的自然推广。与实矩阵相比,复矩阵在数学性质、运算规则和应用场景上具有独特性,尤其在量子力学、信号处理、控制理论等领域发挥关键作用。 复矩阵的定义与表示 定义:复矩阵指的是元素含有复数的矩阵。…

华清远见成都中心嵌入式学习总结

一、Linux 基础入门 课程首先介绍了 Linux 系统的六大特性&#xff0c;包括开源、免费、可裁剪等核心优势。重点讲解了文件系统结构&#xff0c;强调根目录&#xff08;/&#xff09;作为唯一入口的树状结构。通过实操学习了 pwd、ls、cd 等基础命令&#xff0c;掌握了绝对路径…

linux安装ollama

俩种方式都可 一、linux通过docker安装ollama镜像 1.下载安装ollama镜像 # 安装 Docker sudo yum install docker sudo systemctl start docker#docker查看所有容器 docker ps -a # 查看所有容器# docker查看指定容器 docker ps -a |grep ollama# 创建模型存储目录&#xff…

Redis 学习目标

&#x1f3af; Redis 学习目标&#xff08;开发者视角&#xff09; ✅ 一、学习完成后能掌握的核心能力&#xff1a; 分类具体内容&#x1f4e6; 基础能力熟练掌握 Redis 五大数据结构&#xff08;String、List、Hash、Set、ZSet&#xff09;&#xff0c;会用也会选对场景&am…

gerrit配置及使用git-lfs

gerrit服务器端配置 下载git-lfs插件 登录Dashboard [Jenkins] (gerritforge.com)&#xff0c;下载对应版本的插件 配置gerrit 将下载的lfs.jar插件放到${GERRIT_SITE}/plugins/下面为所有仓库启用git-lfs 此步骤需要修改 All-projects 仓库配置&#xff0c;步骤如下 1、克隆仓…

深入理解 Linux PATH 环境变量:配置与优化!!!

深入理解 Linux PATH 环境变量&#xff1a;配置与优化 &#x1f680; 欢迎来到 Linux 环境变量的奇妙世界&#xff01;今天我们来聊聊那个让命令行如鱼得水的幕后英雄——PATH 环境变量&#xff01;&#x1f60e; 通过这篇博客&#xff0c;你将学会如何配置它、优化它&#xff…

如何在AMD MI300X 服务器上部署 DeepSeek R1模型?

DeepSeek-R1凭借其深度推理能力备受关注&#xff0c;在语言模型性能基准测试中可与顶级闭源模型匹敌。 AMD Instinct MI300X GPU可在单节点上高效运行新发布的DeepSeek-R1和V3模型。 用户通过SGLang优化&#xff0c;将MI300X的性能提升至初始版本的4倍&#xff0c;且更多优化将…

简化DB操作:Golang 通用仓库模式

介绍 本代码包提供一个用于数据库操作的通用仓库 (GenericRepository)&#xff0c;利用 Golang 和 GORM (Go ORM) 实现。该仓库设计用于简化数据库的 CRUD (创建、读取、更新、删除) 操作&#xff0c;支持批处理、冲突处理、分页查询等高级功能。 主要功能 创建记录 (Create…

JavaWeb 课堂笔记 —— 08 请求响应

本系列为笔者学习JavaWeb的课堂笔记&#xff0c;视频资源为B站黑马程序员出品的《黑马程序员JavaWeb开发教程&#xff0c;实现javaweb企业开发全流程&#xff08;涵盖SpringMyBatisSpringMVCSpringBoot等&#xff09;》&#xff0c;章节分布参考视频教程&#xff0c;为同样学习…

双引擎驱动:解密音视频体验的QoS技术底座与QoE感官革命

QoS 定义&#xff1a;QoS&#xff08;Quality of Service&#xff0c;服务质量&#xff09;衡量音视频传输技术层面的性能表现&#xff0c;聚焦网络传输和系统处理能力&#xff0c;通过客观指标量化服务质量。核心指标 码率/带宽&#xff1a;数据传输速率上限&#xff0c;直接…

Stable Diffusion + Contronet,调参实现LPIPS最优(带生成效果+指标对比)——项目学习记录

目录 前言 一、数据集&#xff1a;图像文本&#xff0c;部分选取于DeepFashion 二、优化一&#xff0c;img2img 三、优化二&#xff0c;微调sd参数 四、优化三&#xff0c;dreamshaper优化 五、优化四&#xff0c;sdv1.5contronet 六、问题探索历程 1. 从 SDXL 到轻量化模…