JavaScript HTTP 请求:从老古董到新潮流
前端开发离不开跟后端打交道,HTTP 请求就是这座桥梁。JavaScript 提供了好几种方式来发请求,从老牌的 XMLHttpRequest (XHR) 到现代的 Fetch API,再到各种好用的第三方库(像 Axios、Ky、Superagent)。咱们一个一个聊清楚,带代码示例,讲讲优缺点和实际场景,最后再看看未来趋势。
1. XMLHttpRequest (XHR):老大哥还在用
1.1 啥是 XHR?
XHR 是浏览器内置的 API,最早微软在 IE5 搞出来的,后来成了 Web 标准。虽然现在 Fetch 更时髦,但 XHR 在老项目或者需要兼容古老浏览器的场景里还挺常见。
1.2 特点
- 异步支持:可以异步发请求,通过事件监听处理结果。
- 灵活:支持 GET、POST、PUT 等方法,能处理 JSON、文件、甚至二进制数据。
- 兼容性:几乎所有浏览器(包括 IE)都支持。
- 缺点:代码写起来有点繁琐,回调风格容易搞成“回调地狱”。
1.3 怎么用?
来看个简单的 GET 请求:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true); // true 表示异步
xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {console.log(JSON.parse(xhr.responseText)); // 成功拿到数据} else if (xhr.readyState === 4) {console.error('出错了:', xhr.statusText); // 错误处理}
};
xhr.onerror = function () {console.error('网络挂了'); // 网络错误
};
xhr.send();
1.4 POST 请求
如果要发 POST 请求,比如提交个表单数据:
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.example.com/submit', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {console.log('成功:', JSON.parse(xhr.responseText));} else if (xhr.readyState === 4) {console.error('出错了:', xhr.statusText);}
};
const data = JSON.stringify({ name: '小明', age: 25 });
xhr.send(data);
1.5 高级点玩法
- 超时:
xhr.timeout = 5000
设置 5 秒超时。 - 进度监听:用
xhr.onprogress
监听大文件上传/下载进度。 - 取消请求:
xhr.abort()
直接干掉请求。
1.6 优缺点
- 优点:原生支持,兼容性无敌,能监听进度。
- 缺点:代码啰嗦,回调太多,现代项目用起来有点老土。
2. Fetch API:现代前端的标配
2.1 啥是 Fetch?
Fetch 是浏览器的新 API,2015 年开始推广,基于 Promise 设计,写起来比 XHR 清爽多了。现在基本是前端发请求的首选。
2.2 特点
- Promise 风格:支持 async/await,代码简洁。
- 流式处理:可以用 ReadableStream 处理大文件。
- 现代化:API 设计直观,配置简单。
- 缺点:不会自动抛 HTTP 错误(像 404、500),得自己检查;不支持进度事件。
2.3 基本用法
简单的 GET 请求:
fetch('https://api.example.com/data').then(response => {if (!response.ok) {throw new Error(`HTTP 错误! 状态码: ${response.status}`);}return response.json();}).then(data => console.log(data)).catch(error => console.error('出错了:', error));
用 async/await 更清爽:
async function fetchData() {try {const response = await fetch('https://api.example.com/data');if (!response.ok) {throw new Error(`HTTP 错误! 状态码: ${response.status}`);}const data = await response.json();console.log(data);} catch (error) {console.error('出错了:', error);}
}
fetchData();
2.4 POST 请求
发个 POST 请求:
async function postData() {try {const response = await fetch('https://api.example.com/submit', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ name: '小明', age: 25 }),});if (!response.ok) {throw new Error(`HTTP 错误! 状态码: ${response.status}`);}const data = await response.json();console.log('成功:', data);} catch (error) {console.error('出错了:', error);}
}
postData();
2.5 高级玩法
- 流式处理:处理大文件或流式数据:
async function streamData() {const response = await fetch('https://api.example.com/stream');const reader = response.body.getReader();const decoder = new TextDecoder();while (true) {const { done, value } = await reader.read();if (done) break;console.log(decoder.decode(value));} }
- 取消请求:用
AbortController
:const controller = new AbortController(); fetch('https://api.example.com/data', { signal: controller.signal }).then(response => response.json()).then(data => console.log(data)).catch(error => console.error('出错了:', error)); setTimeout(() => controller.abort(), 3000); // 3秒后取消
2.6 优缺点
- 优点:语法简洁,Promise 好用,支持流式处理,跟现代 JS 配合天衣无缝。
- 缺点:得手动检查 HTTP 状态码,IE 不支持,没进度事件。
3. 热门请求库:省心省力
原生的 XHR 和 Fetch 虽然好,但有时候写起来还是麻烦。第三方库把这些都封装得更简单,下面聊聊几个 2025 年还很火的库。
3.1 Axios:万金油选择
啥是 Axios?
Axios 是最流行的 HTTP 客户端,支持浏览器和 Node.js,基于 Promise,功能强大,社区活跃。
特点:
- 自动转 JSON 数据。
- 支持请求/响应拦截器(比如加 token)。
- 支持取消请求、超时。
- 兼容性好,连 IE 都支持。
- GitHub Star(2025 年):大概 100k+。
基本用法:
import axios from 'axios';async function fetchWithAxios() {try {const response = await axios.get('https://api.example.com/data');console.log(response.data);} catch (error) {console.error('出错了:', error.message);}
}// POST 请求
async function postWithAxios() {try {const response = await axios.post('https://api.example.com/submit', {name: '小明',age: 25,});console.log('成功:', response.data);} catch (error) {console.error('出错了:', error.message);}
}
拦截器(超实用):
axios.interceptors.request.use(config => {config.headers.Authorization = `Bearer ${token}`;return config;
});axios.interceptors.response.use(response => response,error => {console.error('全局错误:', error);return Promise.reject(error);}
);
优点:
- API 简单,功能全。
- 支持全局配置,适合大项目。
- 自动处理 HTTP 错误。
缺点:
- 得引入库,增加点体积(压缩后 ~20KB)。
- 小项目可能用不上这么多功能。
3.2 Ky:轻量又时髦
啥是 Ky?
Ky 是基于 Fetch 的轻量库,专为现代浏览器设计,API 优雅,体积小。
特点:
- 基于原生 Fetch,无需 polyfill。
- API 直观,比如
ky.get().json()
。 - 体积超小(压缩后 ~5KB)。
- 支持超时、重试、JSON 自动解析。
基本用法:
import ky from 'ky';async function fetchWithKy() {try {const data = await ky.get('https://api.example.com/data').json();console.log(data);} catch (error) {console.error('出错了:', error);}
}// POST 请求
async function postWithKy() {try {const data = await ky.post('https://api.example.com/submit', {json: { name: '小明', age: 25 },}).json();console.log('成功:', data);} catch (error) {console.error('出错了:', error);}
}
重试机制:
const data = await ky.get('https://api.example.com/data', {retry: 3,timeout: 5000,
}).json();
优点:
- 超轻量,API 优雅,适合小项目。
- 学习成本低,现代浏览器完美支持。
缺点:
- 不支持 IE。
- 功能比 Axios 简单点,拦截器支持有限。
3.3 Superagent:链式调用很酷
啥是 Superagent?
Superagent 是个轻量 HTTP 客户端,支持浏览器和 Node.js,链式调用风格很独特,适合快速上手。
特点:
- 链式 API(像
.get().query()
)。 - 支持文件上传、超时、认证。
- 体积适中(压缩后 ~15KB)。
基本用法:
import request from 'superagent';async function fetchWithSuperagent() {try {const response = await request.get('https://api.example.com/data');console.log(response.body);} catch (error) {console.error('出错了:', error.message);}
}// POST 请求
async function postWithSuperagent() {try {const response = await request.post('https://api.example.com/submit').send({ name: '小明', age: 25 });console.log('成功:', response.body);} catch (error) {console.error('出错了:', error.message);}
}
优点:
- 链式调用写起来爽,代码可读性高。
- 支持多种数据格式。
缺点:
- 社区没 Axios 活跃。
- 功能比 Axios 少点。
3.4 其他好用的
- SWR:React 专用的数据获取库,带缓存,超适合动态数据场景。
import useSWR from 'swr'; const fetcher = url => fetch(url).then(res => res.json()); const { data, error } = useSWR('https://api.example.com/data', fetcher);
- React Query (TanStack Query):复杂应用的利器,数据同步和状态管理一流。
- Alova:新兴库,支持请求策略(缓存、重试),跟 Vue/React 配合好。
4. 对比:选哪个好?
工具 | 原生? | Promise? | 体积 | 拦截器 | 流式处理 | 取消请求 | 兼容性 | 适合场景 |
---|---|---|---|---|---|---|---|---|
XHR | 是 | 否 | 无需引入 | 不支持 | 支持 | 支持 | 超强(包括 IE) | 老项目、兼容性要求高 |
Fetch | 是 | 是 | 无需引入 | 不支持 | 支持 | 支持 | 现代浏览器 | 现代 Web 开发 |
Axios | 否 | 是 | ~20KB | 支持 | 不支持 | 支持 | 超强(包括 IE) | 企业级、复杂需求 |
Ky | 否 | 是 | ~5KB | 有限 | 支持 | 支持 | 现代浏览器 | 轻量项目、现代浏览器 |
Superagent | 否 | 是 | ~15KB | 有限 | 不支持 | 支持 | 好 | 快速开发、中小型项目 |
选啥?
- 小项目:Fetch 或 Ky,简单轻量。
- 大项目:Axios,功能全,省心。
- React 项目:SWR 或 React Query,数据管理更方便。
- 兼容 IE:用 XHR 或 Axios。
- Web3/实时:Fetch 配合 WebSocket 更灵活。
5. 实战:写个请求工具类
下面是个基于 Fetch 和 Axios 的工具类,方便复用,支持 GET、POST、错误处理和超时:
class HttpClient {constructor(baseURL) {this.baseURL = baseURL;this.axiosInstance = axios.create({baseURL,timeout: 10000,});}async fetchRequest(method, url, data = null, options = {}) {try {const response = await fetch(`${this.baseURL}${url}`, {method,headers: {'Content-Type': 'application/json',...options.headers,},body: data ? JSON.stringify(data) : null,...options,});if (!response.ok) {throw new Error(`HTTP 错误! 状态码: ${response.status}`);}return await response.json();} catch (error) {console.error('Fetch 出错了:', error);throw error;}}async axiosRequest(method, url, data = null) {try {const response = await this.axiosInstance({ method, url, data });return response.data;} catch (error) {console.error('Axios 出错了:', error.message);throw error;}}get(url, options = {}) {return this.fetchRequest('GET', url, null, options);}post(url, data, options = {}) {return this.fetchRequest('POST', url, data, options);}axiosGet(url) {return this.axiosRequest('get', url);}axiosPost(url, data) {return this.axiosRequest('post', url, data);}
}// 用法
const client = new HttpClient('https://api.example.com');async function main() {try {const fetchData = await client.get('/data');console.log('Fetch GET:', fetchData);const axiosData = await client.axiosPost('/submit', { name: '小明' });console.log('Axios POST:', axiosData);} catch (error) {console.error('出错了:', error);}
}
main();
6. 注意事项
- 错误处理:Fetch 不会自动抛 404、500,得自己检查;Axios 自动抛。
- 超时:Fetch 用
AbortController
,Axios 直接配timeout
。 - 安全:
- 用 HTTPS,防止数据泄露。
- 正确设置
Content-Type
和Accept
头。 - 防 XSS/CSRF,检查 CORS 配置。
- 性能:
- 用 SWR 或浏览器 Cache API 缓存数据。
- 压缩请求体(比如 Gzip)。
- 用 CDN 加速静态资源。
- 调试:
- 浏览器 DevTools 的 Network 面板。
- Postman 或者 Insomnia 测试 API。
- Axios 的拦截器可以打日志。
7. 未来趋势
- GraphQL:越来越多人用 GraphQL 替代 REST,推荐 Apollo Client 或 urql。
- Server Components:React 19 和 Next.js 15 的服务器组件减少客户端请求,性能更好。
- WebTransport:新 API,可能取代部分 HTTP 请求,延迟更低。
- AI 辅助:AI 工具(像 Vercel 的 v0)可能自动生成请求代码,优化 API 调用。
8. 总结
- XHR:老项目或兼容 IE 用,代码有点烦。
- Fetch:现代标配,Promise 和流式处理很强,但得手动处理错误。
- Axios:大项目首选,功能全,社区强。
- Ky:小项目利器,轻量又好用。
- Superagent:链式调用爽,适合快速开发。
根据项目需求选工具:小项目用 Fetch/Ky,大项目选 Axios,React 开发试试 SWR 或 React Query。想动手试试?可以拿上面的工具类改改,调个公开 API(比如 JSONPlaceholder)练练手!
点个收藏,关注前端结城,一起用代码点亮前端世界!🚀