在前端开发中,和后端接口打交道是家常便饭。无论是获取用户信息、提交表单数据,还是加载动态列表,都离不开网络请求。今天我们就从最基础的XMLHttpRequest(Ajax 的核心)讲起,再到现代的Fetch API,带你一步步掌握前端接口调用的核心用法,让你轻松实现数据交互。
一、先搞懂:Ajax 到底是什么?
很多人常说的 “发 Ajax 请求”,本质上是使用XMLHttpRequest(简称 XHR)对象发起的异步网络请求。它的核心优势是异步—— 不用刷新整个页面,就能和服务器交换数据、更新页面内容,这也是现代网页 “无刷新交互” 的基础。
1. 原生 Ajax(XMLHttpRequest)完整示例
我们先写一个完整的 GET 请求示例,再拆解每一步的作用:
javascript
// 1. 创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
// 2. 配置请求方式、接口地址和是否异步
// 参数1:请求方法(GET/POST等),参数2:接口URL,参数3:是否异步(默认true)
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);
// 3. 设置请求头(可选,比如发送JSON数据时需要设置Content-Type)
xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
// 4. 监听请求状态变化
xhr.onreadystatechange = function() {
// readyState=4 表示请求已完成,status=200 表示请求成功
if (xhr.readyState === 4 && xhr.status === 200) {
// 解析响应数据(接口返回的是JSON字符串,需要转成JS对象)
const response = JSON.parse(xhr.responseText);
console.log('请求成功,数据:', response);
} else if (xhr.readyState === 4) {
// 请求完成但状态码不是200,说明请求失败
console.error('请求失败,状态码:', xhr.status);
}
};
// 5. 发送请求(GET请求可以不传参数,POST请求需要传入数据)
xhr.send();
关键步骤拆解:
new XMLHttpRequest():创建请求对象,这是所有操作的起点。open(method, url, async):配置请求的基本信息,async默认true表示异步请求(不会阻塞页面其他代码执行)。onreadystatechange:监听请求的状态变化,readyState有 5 个状态:0:未初始化,还没调用open()1:已打开,调用了open()但还没发送请求2:已发送,调用了send(),响应头已接收3:接收中,正在接收响应体数据4:请求完成,数据接收完毕
send():发送请求。如果是 POST 请求,需要把数据作为参数传入:javascript
// POST请求示例 const postData = { title: '新文章', content: '测试数据' }; xhr.open('POST', 'https://jsonplaceholder.typicode.com/posts', true); xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8'); // 数据需要转成JSON字符串发送 xhr.send(JSON.stringify(postData));
2. 原生 Ajax 的优缺点
✅ 优点:兼容性极强,几乎所有浏览器都支持,不需要引入额外库。
❌ 缺点:
- 回调嵌套容易形成 “回调地狱”(多个请求依赖时,代码嵌套层级深,难以维护);
- API 设计比较老旧,事件监听的方式写起来繁琐;
- 没有内置的 Promise 支持,处理异步逻辑不够优雅。
二、现代方案:Fetch API,更简洁的异步请求
为了解决 Ajax 的痛点,ES6 推出了基于 Promise 的Fetch API,它的语法更简洁,支持链式调用,是现在前端网络请求的主流方案之一。
1. 基础 GET 请求示例
javascript
// 调用fetch方法,传入接口URL,默认是GET请求
fetch('https://jsonplaceholder.typicode.com/posts/1')
// 第一个.then处理响应,先判断请求是否成功,再解析JSON数据
.then(response => {
// fetch的状态码判断:只有网络错误时才会reject,HTTP错误(如404/500)会进入resolve
if (!response.ok) {
throw new Error(`HTTP错误,状态码:${response.status}`);
}
// response.json()会把响应体解析成JS对象,返回一个Promise
return response.json();
})
// 第二个.then处理解析后的数据
.then(data => {
console.log('Fetch GET请求成功,数据:', data);
})
// 捕获请求过程中的所有错误(网络错误、HTTP错误、解析错误)
.catch(error => {
console.error('请求失败:', error.message);
});
2. POST 请求示例
javascript
const postData = {
title: 'Fetch提交的文章',
body: '这是用Fetch发送POST请求的测试数据',
userId: 1
};
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST', // 指定请求方法
headers: {
'Content-Type': 'application/json;charset=utf-8', // 告诉服务器发送的是JSON数据
},
body: JSON.stringify(postData) // 数据需要转成JSON字符串
})
.then(response => {
if (!response.ok) {
throw new Error(`请求失败,状态码:${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Fetch POST请求成功,返回数据:', data);
})
.catch(error => {
console.error('请求出错:', error);
});
3. 用 async/await 优化 Fetch 代码
Promise 的链式调用虽然比回调地狱好很多,但多个请求时还是不够直观。搭配 ES7 的async/await,可以把异步代码写成同步的形式,可读性拉满:
javascript
// 封装成async函数
async function fetchPostData() {
try {
// 1. 发送GET请求,await会等待Promise完成
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
// 2. 判断请求是否成功
if (!response.ok) {
throw new Error(`HTTP错误,状态码:${response.status}`);
}
// 3. 解析响应数据
const data = await response.json();
console.log('async/await GET请求成功:', data);
// 4. 发送POST请求
const postResponse = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify({ title: 'async/await提交', body: '测试数据', userId: 1 })
});
if (!postResponse.ok) {
throw new Error(`POST请求失败,状态码:${postResponse.status}`);
}
const postResult = await postResponse.json();
console.log('async/await POST请求成功:', postResult);
} catch (error) {
// 统一捕获所有错误
console.error('请求过程出错:', error.message);
}
}
// 调用函数
fetchPostData();
4. Fetch API 的优缺点
✅ 优点:
- 语法简洁,基于 Promise,支持
async/await,代码可读性高; - 是浏览器原生 API,不需要引入第三方库;
- 支持更多现代特性(如流式响应、跨域配置)。
❌ 缺点:
- 对低版本浏览器兼容性不如原生 XHR(不过现代浏览器都已支持);
- 默认不携带 Cookie,需要手动配置
credentials: 'include'; - 没有内置的请求超时和取消机制(可以通过
AbortController实现); - HTTP 错误状态码(如 404/500)不会触发
reject,需要手动判断response.ok。
三、Ajax vs Fetch:核心区别对比
为了帮你快速理解两者的差异,这里整理了一个对比表:
表格
| 特性 | 原生 Ajax(XMLHttpRequest) | Fetch API |
|---|---|---|
| 语法风格 | 回调函数 / 事件监听 | Promise 链式调用 + async/await |
| 错误处理 | 状态码判断 + 回调分支 | 需手动判断response.ok,错误统一catch |
| 浏览器兼容性 | 所有浏览器兼容,包括低版本 IE | IE 不支持,现代浏览器支持 |
| Cookie 携带 | 默认携带 | 默认不携带,需配置credentials |
| 超时 / 取消机制 | 有timeout属性和abort()方法 | 需配合AbortController实现 |
| 代码简洁度 | 繁琐,配置项多 | 简洁,语义化强 |
四、实战小技巧:处理接口请求的常见问题
1. 实现请求超时(Fetch)
Fetch 本身没有超时配置,可以用Promise.race实现:
javascript
function fetchWithTimeout(url, options = {}, timeout = 5000) {
// 创建一个超时的Promise,5秒后reject
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('请求超时')), timeout);
});
// Promise.race会返回第一个完成的Promise的结果
return Promise.race([fetch(url, options), timeoutPromise]);
}
// 使用示例
async function testTimeout() {
try {
const response = await fetchWithTimeout('https://jsonplaceholder.typicode.com/posts/1', {}, 3000);
const data = await response.json();
console.log('数据:', data);
} catch (error) {
console.error(error.message);
}
}
2. 取消请求(Fetch)
使用AbortController可以随时取消正在进行的请求:
javascript
async function fetchWithCancel() {
const controller = new AbortController();
const signal = controller.signal;
// 3秒后取消请求
setTimeout(() => controller.abort(), 3000);
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1', { signal });
const data = await response.json();
console.log('数据:', data);
} catch (error) {
if (error.name === 'AbortError') {
console.log('请求已被取消');
} else {
console.error('请求出错:', error);
}
}
}
3. 跨域请求配置
如果后端配置了 CORS,Fetch 请求可以直接跨域;如果是携带 Cookie 的跨域请求,需要配置credentials: 'include':
javascript
fetch('https://跨域接口地址', {
method: 'GET',
credentials: 'include' // 携带Cookie
})
五、总结:什么时候用 Ajax,什么时候用 Fetch?
- 原生 Ajax:现在只有在兼容极老的浏览器(如 IE)时才会用到,日常开发基本不用手写原生 XHR 了。
- Fetch API:现代项目中,搭配
async/await使用,是轻量级接口请求的首选,不需要引入第三方库。 - 大型项目中,我们更常用 Axios(基于 Promise 的 HTTP 客户端,封装了 XHR 和 Fetch 的优点,内置超时、拦截器、自动转换数据等功能),但理解 Ajax 和 Fetch 的底层原理,能帮你更好地使用这些封装库。
掌握了 Ajax 和 Fetch,你就掌握了前端和后端交互的核心能力,无论是单页应用还是普通网页,都能轻松实现数据的获取和提交。

383

被折叠的 条评论
为什么被折叠?



