从 XMLHttpRequest 到 Fetch API:现代前端网络请求的演进与迁移指南

从 XMLHttpRequest 到 Fetch API:现代前端网络请求的演进与迁移指南
🧑 博主简介ZEEKLOG博客专家历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可关注公众号 “ 心海云图 ” 微信小程序搜索“历代文学”)总架构师,16年工作经验,精通Java编程高并发设计分布式系统架构设计Springboot和微服务,熟悉LinuxESXI虚拟化以及云原生Docker和K8s,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。
🤝商务合作:请搜索或扫码关注微信公众号 “ 心海云图


在这里插入图片描述

从 XMLHttpRequest 到 Fetch API:现代前端网络请求的演进与迁移指南

引言:为什么我们需要新的网络请求方案?

在前端开发领域,XMLHttpRequest (XHR) 长期统治着浏览器端的网络请求。然而,随着 Web 应用变得越来越复杂,XHR 的设计缺陷和局限性逐渐暴露。2015年,Fetch API 作为更现代、更强大的替代方案出现在 Web 标准中,开启了前端网络请求的新时代。

本文将深入探讨从 XHR 迁移到 Fetch API 的技术细节、优势对比以及实际迁移策略,帮助你理解这一重要技术演进的背后逻辑。

一、XMLHttpRequest 的历史包袱与设计缺陷

1.1 XHR 的基本使用模式

// 典型的 XHR 请求代码var xhr =newXMLHttpRequest(); xhr.open('GET','/api/data',true); xhr.onreadystatechange=function(){if(xhr.readyState ===4){if(xhr.status ===200){var data =JSON.parse(xhr.responseText); console.log('成功:', data);}else{ console.error('请求失败:', xhr.status);}}}; xhr.onerror=function(){ console.error('网络错误');}; xhr.send();

1.2 XHR 的核心问题

回调地狱与复杂的状态管理
XHR 基于事件的回调模式导致代码嵌套层次深,错误处理分散,可读性差。

模糊的错误信息
XHR 的 readyState === 0 状态是最典型的例子 - 它只告诉开发者"请求未初始化",却不提供具体原因。这种模糊性使得调试变得异常困难。

API 设计不直观
需要管理多个事件监听器 (onreadystatechange, onerror, ontimeout),配置复杂,学习曲线陡峭。

功能限制
缺乏对现代 Web 特性(如流式处理、请求中断)的良好支持。

二、Fetch API 的设计理念与核心优势

2.1 Fetch API 的基本使用

// 基础的 Fetch 请求fetch('/api/data').then(response=>{if(!response.ok){thrownewError(`HTTP ${response.status}: ${response.statusText}`);}return response.json();}).then(data=> console.log('成功:', data)).catch(error=> console.error('失败:', error));

2.2 Fetch 的核心设计优势

基于 Promise 的现代化 API

  • 链式调用,避免回调地狱
  • 统一的错误处理机制
  • 更好的异步代码可读性

更精确的错误分类

fetch('/api/data').catch(error=>{// 明确的错误类型if(error.name ==='TypeError'){ console.error('网络错误或 CORS 问题');}elseif(error.name ==='AbortError'){ console.error('请求被取消');}});

对现代 Web 特性的原生支持

  • Service Worker 集成
  • 流式数据处理
  • 请求/响应流的直接访问

三、深度技术对比:XHR vs Fetch

3.1 响应处理机制对比

XHR 的响应处理

xhr.onreadystatechange=function(){if(xhr.readyState ===4){// 所有完成状态都进入这里if(xhr.status ===200){// 成功处理}else{// 所有错误状态统一处理}}};

Fetch 的响应处理

fetch(url).then(response=>{// 关键区别:所有网络成功的请求都进入这里// 包括 200、404、500 等状态码if(response.ok){// 只有 200-299 状态码进入这里return response.json();}elseif(response.status ===304){// 特殊处理缓存情况returnhandleNotModified();}else{// 其他 HTTP 错误状态thrownewHttpError(response.status, response.statusText);}}).catch(error=>{// 只有网络层面的错误进入这里// 如 CORS 错误、DNS 解析失败、网络断开等});

3.2 状态码处理的重大差异

response.ok 的真相

// Fetch 的 response.ok 行为 console.log(response.status);// 200 -> response.ok: true console.log(response.status);// 201 -> response.ok: true  console.log(response.status);// 204 -> response.ok: true console.log(response.status);// 304 -> response.ok: false // 注意! console.log(response.status);// 404 -> response.ok: false console.log(response.status);// 500 -> response.ok: false

这种设计让开发者能够更精确地处理不同的 HTTP 场景,特别是对 304 Not Modified 的特殊处理。

3.3 请求控制能力对比

XHR 的请求控制

var xhr =newXMLHttpRequest(); xhr.open('GET','/api/data',true); xhr.timeout =5000; xhr.ontimeout=function(){ console.log('请求超时');};// 但 XHR 无法真正中止一个超时请求

Fetch 的请求控制

const controller =newAbortController();const signal = controller.signal;// 设置超时setTimeout(()=> controller.abort(),5000);fetch('/api/data',{ signal }).then(response=> response.json()).catch(err=>{if(err.name ==='AbortError'){ console.log('请求被主动取消');}});

四、实际问题解决:状态 0 的谜团

4.1 XHR 状态 0 的根本原因

XHR 的 readyState === 0 表示请求甚至没有成功发送出去,常见原因包括:

  • CORS 跨域问题:浏览器安全策略阻止
  • 网络层阻止:防火墙、代理拦截
  • 代码逻辑错误:在 open()send() 之间发生异常
  • URL 格式错误:协议错误、主机名解析失败

4.2 Fetch 的改进方案

asyncfunctionrobustFetch(url, options ={}){try{const controller =newAbortController();const timeoutId =setTimeout(()=> controller.abort(), options.timeout ||30000);const response =awaitfetch(url,{...options, signal: controller.signal });clearTimeout(timeoutId);if(!response.ok){thrownewHttpError(response.status, response.statusText);}returnawait response.json();}catch(error){// Fetch 提供更明确的错误信息if(error.name ==='AbortError'){thrownewError('请求超时');}elseif(error.name ==='TypeError'){thrownewError('网络错误或 CORS 配置问题');}else{throw error;}}}

五、完整迁移指南与最佳实践

5.1 渐进式迁移策略

创建兼容层

classApiClient{constructor(baseURL =''){this.baseURL = baseURL;this.useFetch =typeof fetch !=='undefined';}asyncrequest(endpoint, options ={}){const url =this.baseURL + endpoint;if(this.useFetch){returnthis.fetchRequest(url, options);}else{returnthis.xhrRequest(url, options);}}asyncfetchRequest(url, options){const controller =newAbortController();const timeoutId =setTimeout(()=> controller.abort(), options.timeout ||30000);try{const response =awaitfetch(url,{ method: options.method ||'GET', headers: options.headers, body: options.body, signal: controller.signal, credentials:'include'});clearTimeout(timeoutId);// 完整的 HTTP 状态码处理switch(response.status){case200:case201:returnawaitthis.parseResponse(response);case204:returnnull;case304:returnthis.handleNotModified(url);case401:thrownewAuthenticationError('请重新登录');case403:thrownewAuthorizationError('没有访问权限');case404:thrownewNotFoundError('资源不存在');case429:thrownewRateLimitError('请求过于频繁');default:if(response.ok){returnawaitthis.parseResponse(response);}thrownewHttpError(response.status, response.statusText);}}catch(error){clearTimeout(timeoutId);throwthis.enhanceError(error, url);}}enhanceError(error, url){if(error.name ==='AbortError'){return{ type:'TIMEOUT', message:`请求超时: ${url}`};}if(error.name ==='TypeError'&& error.message.includes('Failed to fetch')){return{ type:'NETWORK_ERROR', message:`网络连接失败: ${url}`};}return error;}}

5.2 高级特性利用

流式数据处理

// 处理大文件或实时数据流asyncfunctionprocessLargeData(url){const response =awaitfetch(url);const reader = response.body.getReader();while(true){const{ done, value }=await reader.read();if(done)break;// 处理数据块 console.log('接收到数据块:', value.length);}}

请求重试机制

asyncfunctionfetchWithRetry(url, options ={}, maxRetries =3){let lastError;for(let attempt =1; attempt <= maxRetries; attempt++){try{const result =awaitfetch(url, options);return result;}catch(error){ lastError = error;// 只在网络错误时重试if(error.type ==='NETWORK_ERROR'|| error.type ==='TIMEOUT'){const delay = Math.min(1000* Math.pow(2, attempt -1),10000);awaitnewPromise(resolve=>setTimeout(resolve, delay));continue;}// HTTP 错误不重试break;}}throw lastError;}

六、实际业务场景中的迁移考量

6.1 浏览器兼容性处理

// 特性检测与降级方案if(typeof fetch ==='function'&&typeof AbortController ==='function'){// 使用现代 Fetch API module.exports =require('./modern-fetch-client');}else{// 降级到 XHR 或 polyfill module.exports =require('./legacy-xhr-client');}

6.2 与现有代码库的集成

拦截器模式

classFetchInterceptor{constructor(){this.requestInterceptors =[];this.responseInterceptors =[];}use(requestHandler, responseHandler){if(requestHandler)this.requestInterceptors.push(requestHandler);if(responseHandler)this.responseInterceptors.push(responseHandler);}asyncfetch(url, options ={}){// 处理请求拦截器let processedOptions = options;for(const interceptor ofthis.requestInterceptors){ processedOptions =awaitinterceptor(url, processedOptions);}let response =awaitfetch(url, processedOptions);// 处理响应拦截器for(const interceptor ofthis.responseInterceptors){ response =awaitinterceptor(response);}return response;}}

七、性能优化与监控

7.1 请求性能监控

classmonitoredFetch{staticasyncfetch(url, options ={}){const startTime = performance.now();const requestId =generateUniqueId();try{emitEvent('requestStart',{ requestId, url, startTime });const response =awaitfetch(url, options);const endTime = performance.now();emitEvent('requestEnd',{ requestId, url, duration: endTime - startTime, status: response.status, size: response.headers.get('content-length')});return response;}catch(error){const endTime = performance.now();emitEvent('requestError',{ requestId, url, duration: endTime - startTime, error: error.message });throw error;}}}

八、总结:为什么现在应该迁移到 Fetch API

8.1 技术优势总结

  1. 更现代的 API 设计:基于 Promise,支持 async/await
  2. 更精确的错误处理:明确的错误类型和分类
  3. 更好的性能特性:流式处理、请求取消等
  4. 更标准化的规范:WHATWG 标准,持续演进
  5. 更完善的生态系统:与现代框架和工具链深度集成

8.2 业务价值体现

  1. 开发效率提升:代码更简洁,调试更简单
  2. 用户体验改善:更好的错误处理和重试机制
  3. 维护成本降低:统一的技术栈和更少的兼容代码
  4. 技术债务减少:跟上 Web 标准发展,避免被遗留技术束缚

8.3 迁移建议

立即开始:

  • 新项目直接使用 Fetch API
  • 现有项目逐步替换关键的 XHR 调用
  • 建立统一的 HTTP 客户端抽象层

长期规划:

  • 完全移除 XHR 依赖
  • 利用 Fetch 高级特性优化应用性能
  • 参与 Web 标准演进,跟进新的特性

结语

从 XMLHttpRequest 到 Fetch API 的迁移,不仅仅是技术方案的替换,更是前端开发理念的升级。Fetch API 代表了 Web 平台向更现代、更强大方向发展的趋势。

Read more

无人机飞行模式详解

无人机飞行模式详解

一、 按智能程度和操控方式分类(最常见分类) 1. 手动/自稳模式 这是最基础的模式,飞控系统仅辅助保持无人机姿态水平,不进行位置锁定。 特点:操控杆直接控制电机的转速和姿态。松开摇杆,无人机会在惯性下继续漂移,不会自动刹车悬停。 适用:专业飞手、竞速无人机(FPV)、特技飞行。不推荐新手使用。 2. GPS/定位模式 这是最常用、最安全的模式。无人机同时使用GPS、视觉系统和其它传感器来锁定自己的位置、高度和姿态。 特点: 精准悬停:松开摇杆,无人机自动锁定在当前位置和高度,抗风性强。 自动返航:支持一键返航、低电量返航、信号丢失返航。 航线辅助:提供稳定的直线飞行和定点转向。 适用:几乎所有航拍、测绘、巡检等场景。新手必用模式。 3. 运动模式 相当于“运动档”或“飙车模式”

Coze(扣子)全解析:100个落地用途+发布使用指南,小白也能玩转低代码AI智能体

Coze(扣子)全解析:100个落地用途+发布使用指南,小白也能玩转低代码AI智能体

摘要:Coze(扣子)作为字节跳动推出的低代码AI智能体平台,凭借零代码/低代码拖拽式操作、丰富的插件生态和多平台发布能力,成为小白和职场人高效落地AI应用的首选工具。本文全面汇总Coze可实现的100个实用场景,覆盖个人、学习、办公、运营等7大领域,同时详细拆解其生成形态、发布流程和使用方法,帮你快速上手,把AI能力转化为实际生产力,无需专业开发经验也能轻松搭建专属AI应用。 前言 在AI普及的当下,很多人想借助AI提升效率、解决实际问题,但苦于没有编程基础,无法开发专属AI工具。而Coze(扣子)的出现,彻底打破了这一壁垒——它是字节跳动自主研发的低代码AI智能体平台,无需复杂编码,通过拖拽组件、配置插件、编写简单提示词,就能快速搭建聊天Bot、工作流、知识库等AI应用,并且支持多渠道发布,让你的AI工具随时随地可用。 本文将分为两大核心部分:第一部分汇总Coze可落地的100个实用场景,帮你打开思路,找到适配自己需求的用法;第二部分详细讲解Coze生成的应用形态、发布流程和使用技巧,让你搭建完成后快速落地使用,真正实现“零代码上手,高效用AI”。 第一部分:Coze

基于大疆MSDK实现的无人机视觉引导自适应降落功能

基于大疆MSDK实现的无人机视觉引导自适应降落功能 概述 最初需求:想要无人机在执行完航线任务后,一键落到一个指定的位置,简化人工控制。 实现一套完整的无人机自主降落功能,通过虚拟摇杆控制使无人机飞向指定位置,再利用视觉识别引导无人机精确降落到具体位置。本文中采用自适应降落策略,根据高度动态调整精度要求和下降速度,以实现安全、精确的降落。 核心点: * 虚拟摇杆导航替代FlyTo功能 * 双轴(X/Y)位置偏移实时调整 * 高度自适应降落策略 * 视觉识别引导定位 * 智能避障管理 系统架构 整体流程 否 是 高于50m 20-50m 5-20m 低于5m 是 否 是 否 否 是 用户触发Return to Vehicle 获取无人机GPS位置 计算与目标点距离 启动虚拟摇杆导航 飞向目标位置 5m/s 距离小于10m? 开始自适应降落 视觉识别系统 计算X/Y偏移量

基于4G Cat.1模组的AI陪伴教育机器人:政策驱动下的算力与物联网融合新机遇

基于4G Cat.1模组的AI陪伴教育机器人:政策驱动下的算力与物联网融合新机遇

在万物互联与人工智能深度融合的“十五五”规划背景下,基于4G Cat.1模组的AI陪伴教育机器人正迎来历史性发展机遇。2025 年政府工作报告提出持续推进 “人工智能 +” 行动,支持大模型广泛应用;教育数字化已纳入国家战略部署,教育部等九部门《关于加快推进教育数字化的意见》明确将人工智能融入教育教学全要素全过程,推动智能教育装备普及与教育智能化升级。与此同时,工信部等六部门 2023 年联合印发的《算力基础设施高质量发展行动计划》提出,到 2025 年智能算力占比达到 35%,为教育 AI 终端与边缘计算提供坚实算力支撑。在政策与技术双重驱动下,4G Cat.1模组凭借低功耗、广覆盖、高性价比的核心优势,正成为AI教育机器人领域的“黄金连接载体”,为教育数字化转型提供稳定可靠的技术底座。 政策红利:算力与教育融合的“双轮驱动” “十五五”规划与最新政府工作报告为教育数字化转型提供了强有力的政策支撑,尤其对AI教育终端与算力基础设施的融合应用提出了明确方向与要求。 1. 国家战略层面:AI教育终端是重要应用方向 2025 年《政府工作报告》