Express框架POST请求返回JSON响应客户端读取异常排查
问题产生原因
- Fetch API的原生设计就是如此:请求返回的
Response对象不会直接把解析好的响应内容挂在属性上供直接读取,response.body本身就是ReadableStream类型的流式读取对象,设计初衷是支持大体积响应的分段加载,必须调用内置的解析方法才能拿到可用的结构化数据。你直接打印response.body,拿到的自然是未经过解析的流实例,也就是控制台输出的带locked属性的ReadableStream对象。 - 你的服务端代码还存在JSON二次序列化的问题:Express提供的
res.json()方法会自动把传入的JS对象序列化为JSON字符串、设置Content-Type: application/json响应头后返回给客户端。你手动先调用一次JSON.stringify()把对象转成字符串再传给res.json(),会导致返回内容被二次转义,前端即使解析完成,拿到的也会是字符串而非预期的可直接读取属性的JSON对象。
正确实现方式
客户端修复
针对JSON格式的响应,调用Response对象的json()方法即可完成流的读取与JSON解析,该方法返回Promise,解析完成后可拿到结构化的响应数据。修正后的请求逻辑如下:
document.getElementById("continue").addEventListener("click", function() { var username = document.getElementById("username").value; var password = document.getElementById("password").value; if(username != "" && password != "") { const data = { username, password }; console.log(JSON.stringify(data)); const options = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }; fetch(urllogin, options) .then(response => { // 先校验响应状态,避免4xx/5xx错误进入解析流程 if (!response.ok) { throw new Error(`请求异常,状态码:${response.status}`); } // 解析JSON格式响应体 return response.json(); }) .then(resData => { // 此处即可拿到解析完成的业务数据 console.log('登录接口响应:', resData); // 后续登录成功/失败的业务逻辑写在此处 }) .catch(err => { console.error('请求失败:', err); }); } });
补充:如果接口返回纯文本,用
response.text()解析;返回二进制文件(图片、文件流等)则用response.blob()或response.arrayBuffer()解析,根据接口返回的Content-Type选择对应方法即可。
服务端修复
去掉res.json()里的手动序列化逻辑,直接传入响应对象即可,修正后的接口代码:
app.post("/login", (req, res) => { console.log(req.body); const response = { body:'hello' }; // res.json 内部自动完成JSON序列化与响应头设置,无需手动调用JSON.stringify res.json(response); });
修复后前端拿到的resData就是结构为{body: 'hello'}的普通JavaScript对象,可直接读取属性使用。
内容的提问来源于stack exchange,提问作者Luka Petkovic
相关产品推荐
相关产品推荐

