← 返回目录

5. POST 请求体与同步/异步

GET 把参数拼在 URL 上,POST 把参数揣在请求体(send)里发出去

POST 三要素:
1. open——第一个参数写 'post'
2. setRequestHeader——必写表单请求头
3. send——参数字符串放这里

坑:POST 参数不能拼 URL、忘了 setRequestHeader 后端认不出格式、open 第三个参数默认 true 异步别写成 false

5.1 互动演示(模拟登录 POST,本地模拟)

点登录,看 POST 请求体的组装方式(本地模拟,实际开发需后端接口)。

5.2 知识点讲解

1. GET 和 POST 到底差在哪?

最大的区别就是参数放哪。GET 把参数拼在 URL 后面(?page=1&size=10),POST 把参数放在请求体里(send 里),URL 干干净净。

// GET:参数拼在 URL 上,一眼能看见
xhr.open('GET', '/list?page=1&size=10', true);

// GET 没有请求体,send 给 null
xhr.send(null);

// POST:参数不拼 URL,放 send 里
xhr.open('POST', '/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

// 参数揣兜里
xhr.send('username=zhangsan&password=123456');

登录、提交表单、上传数据这类"往服务器写东西"的用 POST;查询、拿列表这类"只读"的用 GET。POST 参数不在 URL 里,相对安全一些(但也不是加密,敏感数据该 https 还是要 https)。

2. 为什么 POST 必须 setRequestHeader?

POST 的请求体可以是各种格式:表单格式、JSON 格式、文件二进制……后端不知道你发的是哪种,所以你得用请求头告诉它"我发的是表单格式"。这一行少写,后端就按默认方式解析,经常把你的参数读成乱码。

// 表单格式(最常见,和原生 form 提交一样)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 参数长这样:username=zhangsan&password=123456

// JSON 格式(现在前后端分离更常用)
xhr.setRequestHeader('Content-Type', 'application/json');
// 参数长这样:'{"username":"zhangsan","password":"123456"}'

发什么格式,就声明什么 Content-Type,两边必须对上。前端发表单格式,后端按表单解析;前端发 JSON,后端按 JSON 解析。对不上就"参数收不到"。

3. 同步和异步:open 的第三个参数

xhr.open(method, url, async) 第三个参数就是"是否异步"。默认 true(异步)——请求发出去后浏览器继续干别的事,数据回来了再触发 onreadystatechange。写成 false 就是同步——浏览器会卡在那一行等服务器返回,期间页面整个卡死点不动。

// 异步(默认,永远这么写):
// true = 异步,不卡页面
xhr.open('POST', '/login', true);

// 回来再回调
xhr.onreadystatechange = function () { ... };

xhr.send(params);

// 同步(几乎不要这么写):
// false = 同步,页面卡死
xhr.open('POST', '/login', false);

// 卡到服务器返回才往下走
xhr.send(params);

// 这里直接能拿到
let data = xhr.responseText;

永远用异步(true 或不传)。同步会冻结整个页面,用户以为浏览器崩了。现在没人用同步 XHR,fetch / axios 默认也都是异步。

4. 实战:用在哪 / 常见坑 / 怎么解决

可能在什么地方用:登录注册、提交表单、发表评论、上传数据、改个人资料——凡是"往服务器写"的接口都是 POST。

常见的问题:

1. POST 参数拼到 URL 上去了(应该放 send)
2. 忘了 setRequestHeader,后端收不到参数
3. Content-Type 和参数格式对不上(发了 JSON 却声明表单)
4. 把 open 第三个参数写成 false,页面卡死。

解决思路:参数收不到就去 Network 看 Payload 里到底发出去了什么;格式问题就核对 Content-Type 和参数串长得对不对;页面卡死就是同步了,改回 true。

一句话:POST = open('post') + setRequestHeader(表单格式) + send(参数串);参数放 send 不拼 URL;第三个参数永远 true(异步)

5.3 课后作业(融入本节)

练习:POST 登录
1. 用原生 XHR 写一个 POST 登录请求,参数 username / password 放 send
2. 加上 setRequestHeader,声明表单格式
3. 在 onreadystatechange 里判断 readyState===4 && status===200,再 JSON.parse
4. 把 Content-Type 改成 application/json 再试一次,观察参数格式变化。

本页重点

API作用参数怎么传返回/结果代码示例
xhr.open("post",url)用 POST 方式发请求入参:"post"、地址返回:无xhr.open("post", "/login", true);
xhr.setRequestHeader(k,v)告诉后端参数是什么格式入参:"Content-Type"、表单格式返回:无xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(body)把参数揣兜里发出去入参:参数字符串返回:无xhr.send("account=zs&pwd=123");
xhr.status===200判断这次请求成功没返回:true / falseif (xhr.status === 200) { }