本文系统梳理了前端请求技术的演进历程,横向对比 XHR、Fetch、Axios、Server Action 的核心特性与适用场景。揭示了每一次技术跃迁背后的核心驱动力!
目录
一、Form表单请求
在早期前后端未分离的时代,web开发者主要使用form表单来发送请求,这种请求在发送之后会刷新整个页面,如下形式👇
<form
action="/submit"
method="post"
enctype="multipart/form-data"
onsubmit="return validateForm()"
>
<!-- 文本输入 -->
<label for="username">用户名:</label>
<input
type="text"
id="username"
name="username"
required
placeholder="输入用户名"
>
<br>
<!-- 密码输入 -->
<label for="password">密码:</label>
<input
type="password"
id="password"
name="password"
required
minlength="6"
>
<br>
<!-- 文件上传 -->
<label for="avatar">上传头像:</label>
<input
type="file"
id="avatar"
name="avatar"
accept="image/*"
>
<br>
<!-- 提交按钮 -->
<input type="submit" value="注册">
</form>
Form的核心属性
-
method
定义数据提交的 HTTP 方法:-
GET
:数据通过 URL 参数传递(明文,适合非敏感数据)。 -
POST
:数据放在请求体中传输(适合敏感数据或文件上传)。
-
-
action
指定表单提交的服务器端 URL(如/login
)。 -
enctype
定义数据编码方式:-
application/x-www-form-urlencoded
(默认):普通文本数据(如key1=value1&key2=value2
)。 -
multipart/form-data
:支持文件上传(必须设置)。 -
text/plain
:纯文本格式(极少使用)。
-
Form请求的局限性
-
页面强制刷新,用户体验差。比如表单提交后,浏览器会重新加载整个页面,导致用户操作中断。
-
无法实现实时数据验证。只能在提交时通过服务器返回错误(如“用户名已存在”),无法在用户输入时实时校验。
-
仅支持键值对数据(
key=value
),直接上传复杂结构(如嵌套 JSON)或二进制文件(如图片、视频)时处理繁琐。 -
React、Vue 等框架倡导组件化和状态驱动,传统表单的同步提交机制难以融入这种模式
-
传统表单难以实现请求取消、超时处理、进度监控(如文件上传进度条)。
二、XMLHttpRequest
XMLHttpRequest
(XHR) 是浏览器提供的 JavaScript API,用于在客户端与服务器之间进行异步 HTTP 请求。它是实现 Ajax(Asynchronous JavaScript and XML)技术的核心,允许网页在不重新加载的情况下与服务器交换数据,从而实现动态内容更新。XHR的基本使用步骤如下👇
// 创建 XHR 对象
const xhr = new XMLHttpRequest();
// 配置请求(请求方法、请求地址、是否为异步请求)
xhr.open('GET', 'https://api.example.com/data', true); // 异步请求
// 设置回调函数
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status === 200) { // 成功状态码
console.log('响应数据:', xhr.responseText);
} else {
console.error('请求失败:', xhr.statusText);
}
}
};
// 发送请求
xhr.send();
XML: XML的全称是可扩展标记语言,主要用于存储和传输数据。它类似于HTML,但HTML用于显示数据,XML用于承载数据。例如,XML的标签是自定义的,比如<person><name>张三</name></person>,这样的结构可以灵活地表示数据。
关键属性和方法
-
属性:
-
readyState
:请求状态(0-4,4 表示完成)。 -
status
:HTTP 状态码(如 200、404)。 -
responseText
:响应文本数据。 -
responseXML
:XML 格式的响应数据(若内容类型匹配)。
-
-
方法:
-
open(method, url, async)
:初始化请求。 -
send(body)
:发送请求(GET 请求体为空,POST 可传数据)。 -
setRequestHeader(key, value)
:设置请求头。 -
abort()
:取消请求。
-
事件监听
-
onreadystatechange
:监听请求状态变化。 -
onprogress
:跟踪数据传输进度(如上传/下载)。 -
onerror
:处理网络错误。
局限性
-
XHR 的 API 基于事件和回调,需要手动处理状态(如
readyState
)和错误,代码冗余。 -
多个异步请求嵌套时,代码可读性差,形成“回调地狱”。
-
原生 XHR 不返回 Promise,与现代异步编程模式不兼容。
-
XHR 一次性接收完整响应,无法流式处理大数据(如实时视频流)。
三、AJAX
全称 Asynchronous JavaScript And XML,翻译过来就是“异步的Javascript
和 XML”。允许浏览器在不重新加载整个页面的情况下,通过后台与服务器交换数据并局部更新页面内容,从而提升用户体验。AJAX是一种概念模式,不是单一技术,而是多种技术的组合:
-
XHR 或 Fetch API:用于发送异步请求。
-
JavaScript/DOM:处理数据和更新页面。
-
JSON/XML:数据格式(现代以 JSON 为主)
为什么会出现AJAX?👉在 AJAX 技术出现之前,如果浏览器需要从服务器请求资源,其核心链路是:
-
客户端发出资源请求;
-
服务端接收请求并返回相应 HTML 文档;
-
页面刷新,客户端加载新的 HTML 文档;
在老旧的模式下,用户的每一次点击都会造成页面的刷新或跳转,这当然很难令人满意。另一方面,当用户点击页面中的某个按钮向服务器发送请求时,页面本质上只是一些数据发生了变化,而此时服务器却要将整个页面再返回给浏览器加载,这种交互方式也会给用户的网络带宽带来不必要的开销。那么有没有办法在页面数据变动时,只向服务器请求新的数据,并且在阻止页面刷新的情况下,动态的替换页面中的数据呢? -- 没错!答案正是 AJAX 技术。
AJAX的核心是XMLHttpRequest
对象,如何利用 XMLHttpRequest
模块实现 Ajax?👇
<body>
<script>
//这里利用 XMLHttpRequest 模块实现了一个最简单的 get 网络请求。
function ajax(url){
// 1. 创建 XHR 对象
const xhr = new XMLHttpRequest();
// 2. 配置 GET 请求(异步模式)
xhr.open('GET', url, true);
// 3. 设置回调函数
xhr.onreadystatechange = function() {
// 4. 检查请求状态和 HTTP 状态码
if (xhr.readyState === 4) { // 请求完成
if (xhr.status >= 200 && xhr.status < 300) { // 成功状态码
// 5. 解析响应数据(假设返回 JSON)
const data = JSON.parse(xhr.responseText);
console.log('响应数据:', data);
} else {
console.error('请求失败:', xhr.status, xhr.statusText);
}
}
};
// 6. 发送请求(GET 无需请求体)
xhr.send();
}
ajax('https://smallpig.site/api/category/getCategory')
</script>
</body>
XHR虽然功能强大,但API设计复杂,配置繁琐,回调方式不够友好,而且在处理跨域请求和二进制数据时不够方便。随着前端应用复杂度的增加,需要更现代、更强大的工具,Fetch应运而生。此外,ES6引入的Promise为Fetch提供了基础,使其能够以更现代的方式处理异步操作。
四、Fetch
Fetch API 是在 ES6 出现的,它基于 ES6 提出的 promise 对象,这使得异步处理更加方便,避免了回调地狱。Fetch默认支持流式数据处理,这在处理大文件或实时数据时很有用。并且,Fetch整合了CORS、请求和响应对象的标准化。
Fetch可以说是
XMLHttpRequest
的替代品,也是对AJAX思想的实现,其与XMLHttpRequest
平级。
Fetch的示例代码:
<body>
<script>
function ajaxFetch(url) {
fetch(url).then(res => res.json()).then(data => {
console.info(data)
})
}
ajaxFetch('https://smallpig.site/api/category/getCategory')
</script>
</body>
Fetch是一个真实存在的API,可以直接使用,并且返回一个promise对象用于链式调用,解决了回调地狱问题
特点:
-
使用
Promise
处理异步操作,告别回调地狱,支持async/await
语法。 -
便于流式数据处理,支持
ReadableStream
,允许逐块处理大数据(如视频、日志流)。 -
支持在离线场景中拦截并缓存 Fetch 请求(Service Worker),通过
Cache-Control
头灵活控制缓存行为。 -
减少代码量,使逻辑更加清晰👇
// XHR 发送 POST 请求 const xhr = new XMLHttpRequest(); xhr.open('POST', url); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = () => { /* ... */ }; xhr.send(JSON.stringify(data)); // Fetch 发送 POST 请求 fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) });
局限性:
-
只有在网络故障时才会reject,HTTP错误状态(如404、500)依然会resolve,需要手动检查
response.ok
。 -
不支持请求超时的直接设置,需要借助
AbortController
来实现。 -
默认不携带cookie,需要显式设置credentials选项。
-
无法像 XHR 的
upload.onprogress
直接监控上传进度。
Fetch API虽然强大,但在某些方面不够完善,比如错误处理、请求取消、上传进度监控等。而XHR的API设计较为老旧,使用起来不够方便。Axios
提供一个更友好、功能更全面的HTTP客户端。
五、Axios
Axios
是一个基于Promise的网络请求的第三方库,它的核心特点包括Promise封装、拦截器、自动转换JSON数据等。Axios
简化了HTTP请求的处理,统一了浏览器和Node.js的环境,提供了更丰富的功能,如拦截器、取消请求等,提高了开发效率和代码的可维护性。
特点
-
基于Promise的异步处理,提供链式调用和
async/await
支持,代码简洁易读。 -
浏览器端基于
XMLHttpRequest
,Node.js 端基于http
模块,无缝适配不同环境。 -
全局拦截请求和响应,实现统一逻辑(如添加 Token、处理错误)。
-
自动将请求体序列化为 JSON,并解析响应数据为 JSON。(XHR、Fetch都需手动处理JSON)。
-
通过
CancelToken
或AbortController
取消进行中的请求。 -
支持监听文件上传和下载的进度。
-
自动携带
XSRF-TOKEN
Cookie,增强安全性。(Fetch默认不携带Cookie)
async关键字将函数标记为异步函数,await关键字等待 Promise对象完成
局限性
-
Axios
大小约 10KB(gzip),对极简项目可能造成冗余。如对项目的体积要求较高,建议使用原生Fetch
或轻量库(如ky
,大小约 3KB)。 -
部分功能需手动配置实现。
六、Sever Action
Server Action(服务器动作) 是一种在现代全栈框架(如 Next.js、Remix、SvelteKit)中广泛使用的技术,允许开发者直接在服务器端执行逻辑,并通过无缝集成的前后端代码处理用户交互(如表单提交、数据修改)。其核心思想在于将传统需要在客户端(浏览器)与服务器之间通过 API 接口通信的流程,简化为直接在服务器端处理用户请求,减少客户端代码复杂度并提升安全性。
Server Action简化了全栈开发流程,目前在学习全栈开发的小伙伴可以了解一下!
┌───────────────────────┐ ┌───────────────────────┐
│ 同步时代 (1990-2004) │ │ 全栈未来 (2024+) │
│ │ │ │
│ ● 原生 Form 表单 │ │ ● Server Action │
│ └ 同步提交/页面刷新 │ │ └ 服务端直接处理 │
│ └ 基础表单验证 │ │ └ 零API/深度集成 │
└───────────┬───────────┘ └───────────┬───────────┘
│ │
│ │
▼ ▼
┌───────────────────────┐ ┌───────────────────────┐
│ 异步革命 (2005-2014) │ │ 封装艺术 (2020-2023) │
│ │ │ │
│ ● XMLHttpRequest │ │ ● Axios │
│ └ 异步无刷新 │───────┐ │ └ 拦截器/自动JSON │
│ └ 回调地狱 │ │ │ └ 请求取消/进度监控 │
└───────────┬───────────┘ │ └───────────┬───────────┘
│ │ │
│ │ │
▼ │ ▼
┌───────────────────────┐ │ ┌───────────────────────┐
│ 标准之光 (2015-2019) │ │ │ 现代替代方案 │
│ │ │ │ │
│ ● Fetch API │◀──────┘ │ ● Ky/Redaxios │
│ └ 基于Promise │ │ └ 轻量级封装 │
│ └ 流式数据/简洁API │ │ ● WebSocket/SSE │
└───────────────────────┘ └───────────────────────┘
技术选型指南
-
简单请求 & 现代浏览器:优先选择 Fetch API(轻量、原生支持)。
-
复杂功能需求:使用 Axios(拦截器、上传进度、错误统一处理)。
-
全栈开发 & 表单场景:采用 Server Action(Next.js/Remix 框架中高效开发)。
-
兼容旧项目 & 低版本浏览器:保留 XHR 或引入 Polyfill(如
whatwg-fetch
)。 -
无 JavaScript 环境:原生 Form 表单提交作为兜底方案。