你有没有过这种经历:盯着浏览器控制台,看着那个请求一直转圈,状态栏里写着 (pending)...,或者干脆跳出来一个刺眼的红色 408 Request Timeout?那一刻,你的代码没报错,逻辑也没bug,但数据就是死活不来。
别急,这大概率不是你的逻辑坏了,而是你对 AJAX(Asynchronous JavaScript and XML) 这个老伙计还不够“知心”。今天咱们不背教科书,我就把你当成我的一个前端小伙伴,咱们泡杯咖啡,一边撸代码,一边把 GET 和 POST 那点事儿,以及那些让人头秃的“卡住”问题,聊得明明白白。
一、 先别急着改代码,看懂“网络面板”才是第一步
很多初学者遇到请求失败,第一反应是 console.log 到处插,然后问:“为什么我的请求没发出去?”
其实,Chrome DevTools 的 Network(网络) 面板早就告诉你答案了,只是你可能只看了结果,没看过程。
1. 那个让你焦虑的 “(pending)” 是什么?
当你打开 Network 面板,看到一个请求的状态一直卡在 pending,甚至时间拉长到几秒、几十秒:
- 如果状态码是空白:说明浏览器还在等待服务器的响应头。这通常意味着网络通了,但服务器“装死”了,或者中间有代理/防火墙在拦截。
- 如果是
canceled:那就是你主动取消了,或者页面刷新了,或者是被浏览器自己拦截了(比如跨域没设好)。 - 如果是
failed:通常是网络断开,或者服务器直接拒绝连接(Connection Refused)。
真实案例:
有一次我调试一个接口,请求一直 pending。我以为是后端没处理,结果把 URL 放到 Postman 里,秒返回。最后发现是 Chrome 的 Preload Connections 功能在捣鬼,加上我本地开了个代理,导致握手卡住。关了代理,或者换个 curl 命令一测,立马破案。
2. 为什么有时候请求根本没出现在 Network 里?
这最坑。你代码写对了,但请求消失了。
- 被 CORS 拦截:这是最常见的“隐形杀手”。浏览器发出
preflight(预检)请求,如果服务器没返回正确的Access-Control-Allow-Origin头,浏览器会直接丢弃后续的真实请求。你在 Network 里可能只看到一个 OPTIONS 请求失败了,或者根本看不到你写的fetch请求。 - 语法错误:JS 代码在发送请求之前就报错了,请求根本没发出去。打开 Console 面板,看有没有红色的报错。
- 条件判断未触发:检查一下你的
if或await逻辑,是不是前置条件没满足?
二、 GET vs POST:别再混着用,选对姿势才高效
AJAX 的核心就是 fetch 或 axios,而它们最基础的两种方法就是 GET 和 POST。很多人觉得它们差不多,不就是换个动词吗?错!选错了,轻则性能差,重则数据泄露、安全背锅。
1. GET:像寄明信片,公开透明
特点:
- 数据附在 URL 后面,比如
https://api.example.com/users?page=1&size=10。 - 数据长度受限(浏览器和服务器都对 URL 长度有上限,通常 2KB - 8KB)。
- 会被浏览器缓存,出现在历史记录里,记录在服务器日志中。
- 幂等:多次执行 GET 请求,结果应该是一样的,不会改变服务器状态。
适用场景:
- 查询数据(搜索、列表加载)。
- 获取资源(用户信息、商品详情)。
- 需要收藏或分享链接的场景。
代码示例:
// 用 fetch 发起 GET 请求
fetch('https://api.example.com/products?category=shoes&sort=price_asc', {
method: 'GET',
headers: {
'Accept': 'application/json'
}
})
.then(response => {
if (!response.ok) throw new Error('网络响应异常');
return response.json();
})
.then(data => console.log('数据来了:', data))
.catch(error => console.error('搞砸了:', error));
2. POST:像寄密封公文,安全可靠
特点:
- 数据放在请求体(Body)里,URL 干干净净。
- 数据大小几乎没有限制(受服务器配置影响,可以传大文件、长文本)。
- 不会被缓存,不会出现在历史记录里,相对安全(但仍需 HTTPS)。
- 非幂等:POST 通常用于创建资源,每次请求可能产生不同的结果(比如每次下单都生成一个新订单号)。
适用场景:
- 提交敏感信息(密码、身份证号、银行卡)。
- 上传文件(图片、PDF)。
- 创建新数据(注册账号、发布文章)。
- 数据量大,超过 URL 长度限制。
代码示例:
// 用 axios 发起 POST 请求(更简洁)
import axios from 'axios';
const sendData = async () => {
try {
const response = await axios.post('https://api.example.com/orders', {
userId: 123,
productId: 'shoe_001',
quantity: 2,
// 敏感信息放这里,URL 里看不到
paymentMethod: 'credit_card'
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your_token_here'
}
});
console.log('下单成功,订单号:', response.data.orderId);
} catch (error) {
// 处理错误,比如 400 表示参数错误,401 表示未登录
console.error('下单失败:', error.response?.data?.message || error.message);
}
};
3. 一张表看懂区别
| 特性 | GET | POST |
|---|---|---|
| 数据位置 | URL 查询参数 | 请求体 (Body) |
| 数据长度 | 受限(~2KB) | 基本无限 |
| 缓存 | 可被浏览器缓存 | 不缓存 |
| 历史记录 | 会保留 | 不会保留 |
| 安全性 | 低(数据明文可见) | 较高(但仍需 HTTPS) |
| 幂等性 | 幂等(安全) | 非幂等(危险操作) |
| 典型用途 | 查询、搜索 | 提交、创建、更新 |
三、 请求卡住或超时的“侦探手册”
回到最初的问题:请求卡住、超时。这不是玄学,是有迹可循的。咱们按顺序排查,像侦探一样破案。
第一步:检查超时设置(Timeout)
很多时候,请求不是“卡住”了,而是“慢”到让你怀疑人生。前端默认的超时时间可能很长,或者根本没设。
解决方案:给 fetch 或 axios 加上超时限制,别让它无限等待。
// axios 设置超时 5 秒
axios.get('/api/slow-endpoint', {
timeout: 5000 // 5000 毫秒 = 5 秒
})
.then(res => console.log(res.data))
.catch(error => {
if (error.code === 'ERR_BAD_REQUEST') {
console.log('请求错误');
} else if (error.code === 'ECONNABORTED' || error.message.includes('timeout')) {
console.log('请求超时了,别等了');
} else {
console.log('其他错误:', error.message);
}
});
提示:超时时,Network 面板里请求状态会变成 failed,原因通常是 ERR_CONNECTION_TIMED_OUT 或类似字样。
第二步:排查跨域问题(CORS)
这是前端最常见的“鬼故事”。请求发出去了,但浏览器拦截了。
现象:
- Console 报错:
Access to fetch at '...' from origin '...' has been blocked by CORS policy - Network 面板:请求状态显示
(failed)或canceled,没有具体的状态码,或者状态码是0。
解决方案:
- 后端配合:让后端在响应头加上
Access-Control-Allow-Origin: *(开发环境)或你的域名(生产环境)。 - 前端代理:如果后端改不了,可以在前端项目中配置代理。比如用 Vite 或 Create React App:
// vite.config.js
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:3000', // 后端地址
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
这样,前端的 /api/user 请求会被代理到 http://localhost:3000/user,绕过浏览器的跨域限制。
第三步:检查网络连通性
有时候,问题不在代码,而在网络。
- 检查 WiFi/网线:确保你的设备能上网。
- 检查后端服务:后端有没有启动?端口对不对?用
curl http://localhost:3000/api/test试试,如果 curl 都连不上,那就是后端或服务器的问题。 - 检查防火墙/VPN:有些公司网络会拦截特定的端口或域名。尝试切换网络(比如用手机热点)测试。
第四步:检查请求参数和方法
- 参数拼错:
userId写成userID,后端收不到,可能默认返回 400 或 500,而不是你期望的数据。 - Content-Type 不对:POST 请求如果发的是 JSON,但 header 里没写
Content-Type: application/json,后端可能解析不了 Body,导致请求卡住或报错。
// 错误示范:没声明 Content-Type,后端可能当普通表单解析
fetch('/api/data', {
method: 'POST',
body: JSON.stringify({ name: 'Alice' })
});
// 正确示范
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'Alice' })
});
第五步:检查服务器响应时间
如果请求不报错,但就是慢,可能是后端处理逻辑太重。
- 数据库查询慢:检查 SQL 语句有没有加索引。
- 第三方 API 慢:如果你调的接口依赖其他服务,看看那个服务是不是挂了。
- 日志分析:让后端同事帮忙看下服务器日志,请求到底有没有到达后端?如果到了,处理了多久?
四、 常见错误代码与“人话”翻译
Network 面板里的状态码,是每个前端人都要熟悉的“密码本”。
- 200 OK:成功!数据来了。
- 201 Created:成功创建资源(比如 POST 注册成功)。
- 204 No Content:成功,但没返回数据(比如 DELETE 删除成功)。
- 301⁄302 Moved:重定向。你的请求被转向了另一个 URL。有时候会导致跨域问题,注意检查。
- 400 Bad Request:参数错了。检查你的请求体,是不是少了必填项,或者格式不对。
- 401 Unauthorized:没登录或 token 过期。去登录接口拿个新的 token 再试。
- 403 Forbidden:登录了,但没权限。比如普通用户想访问管理员接口。
- 404 Not Found:接口地址错了。检查 URL 拼写,或者后端这个接口还没开发完。
- 405 Method Not Allowed:用错了方法。比如后端只允许 GET,你非要用 POST。
- 422 Unprocessable Entity:参数格式错了,但能识别。比如邮箱格式不对,年龄不是数字。
- 500 Internal Server Error:后端崩了。别抓前端代码了,去骂后端同学(友好地)。
- 502/503/504 Bad Gateway/Service Unavailable/Timeout:网关或服务器超时。可能是后端挂掉了,或者负载太高。检查服务器状态。
五、 给小朋友讲的“送快递”比喻
如果把 AJAX 请求比作寄快递:
- GET 请求:就像寄一张明信片。收件人地址(URL)和你要说的话(参数)都写在外面,任何人(浏览器历史、服务器日志)都能看到。所以明信片适合写“你好,我在吗?”这种不重要的话,不适合写密码。
- POST 请求:就像寄一个密封的信封。地址写在信封上,但信的内容(Body)包在里面,外面看不到。适合寄情书、身份证复印件、银行卡号。
- Network 面板:就像快递追踪信息。你可以看到包裹(请求)什么时候发出(Sent),什么时候被航空公司(服务器)接收,什么时候派送(Received),如果卡在半路(pending),就知道是物流问题(网络)还是仓库拒收(404/500)。
- 超时:就是快递员等了你太久,你一直没在家,最后他走了,并留下一个“未送达”的标签(timeout)。
六、 总结一下,怎么避免“卡住”
- 别硬等:给所有请求加上合理的
timeout,让失败快速失败,别让用户干等。 - 看清楚:出问题时,先打开 Network 面板,看状态码和 Time,再打开 Console 看报错。
- 选对方法:查数据用 GET,改数据用 POST。别把密码放 URL 里!
- 跨域不怕:后端配好 CORS,或者前端加代理,别瞎猜。
- 联调先测:前后端联调前,让后端提供一个 Swagger 文档或 Postman 集合,自己先跑通,再写前端代码。
前端的数据获取,说难不难,说简单也不简单。它就像你和服务器之间的一条电话线,有时候信号好,通话顺畅;有时候串线、断线,或者对方占线。多看看 Network 面板,多了解 GET 和 POST 的脾气,你就能成为一个能和服务器“顺畅聊天”的前端高手了。
下次再遇到请求卡住,别慌,泡杯茶,打开 DevTools,一步步排查,答案通常就在那里等着你。
