树莓派温度展示项目中Fetch API解析JSON遇语法错误求助
问题
我正在开发一个低依赖JavaScript项目,用于展示树莓派的温度。服务端响应GET请求返回JSON数据,客户端通过网页展示该数据。已通过浏览器和Postman验证服务端工作正常,但客户端使用Fetch API时,两种JSON解析方式均出现语法错误,而调用公开JSON数据源却能正常工作。已尝试以下方案:
- 两种不同的JSON解析方式
- 使用不同的JSON数据源
期望实现服务端JSON的正确获取与解析。
服务端代码
const { spawn } = require("child_process"); const http = require('http'); http.createServer((req, res) => { if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); const temp = spawn('cat', ['/sys/class/thermal/thermal_zone0/temp']); temp.stdout.on('data', function (data) { data = data / 1000; console.log('Temperature: ' + data + '°C'); res.end(JSON.stringify({"temp":data})); }); temp.stderr.on('data', function (data) { res.end(JSON.stringify({"temp":"Unavailable"})); }); } else { res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({"temp":"Unavailable"})); } }).listen((process.argv[2] || 64567), () => { console.log('Server listening on http://localhost:' + (process.argv[2] || 64567)); });
客户端代码
<body> <script defer> await fetch('http://localhost:64567',{mode: 'no-cors'}).then(res => JSON.parse(res)).then(temp => document.getElementById("value").innerHTML = temp.temp); // SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data /* await fetch('http://localhost:64567',{mode: 'no-cors'}).then(res => res.json()).then(temp => document.getElementById("value").innerHTML = temp.temp) // SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data await fetch('https://api.npoint.io/d5a7160bab77dd869b82').then(res => res.json()).then(temp => document.getElementById("value").innerHTML = temp.temp) // This one works */ </script> <h3>Temperature:<span id="value"> </span> °C</h3> </body>
解决方案
核心问题是你在fetch请求中添加的{mode: 'no-cors'},这个设置会让浏览器强制限制对响应内容的访问权限——哪怕服务端返回了正确的JSON,客户端也无法读取和解析。
1. 移除no-cors模式
修改客户端fetch调用,去掉限制模式,同时修正错误的解析方式:
await fetch('http://localhost:64567') .then(res => res.json()) .then(temp => document.getElementById("value").innerHTML = temp.temp) .catch(err => console.error('请求失败:', err));
注意:你第一个写法里JSON.parse(res)是错误的,res是Response对象而非字符串,必须用res.json()来完成解析,这也是第一个报错的直接原因。
2. 处理跨域问题(若客户端与服务端不同源)
如果你的客户端网页是从其他端口/域名打开的(比如用Live Server运行在5500端口),需要在服务端添加CORS响应头,避免跨域报错:
// 在服务端的res.writeHead中添加CORS头 res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Access-Control-Allow-Origin': '*' // 生产环境建议指定具体域名,而非通配符 });
3. 优化服务端数据读取逻辑
spawn的stdout的data事件可能触发多次(虽然读取温度文件概率极低),建议监听close事件确保数据完整:
let tempData = ''; const temp = spawn('cat', ['/sys/class/thermal/thermal_zone0/temp']); temp.stdout.on('data', function (data) { tempData += data; }); temp.on('close', function () { const tempValue = parseFloat(tempData) / 1000; console.log('Temperature: ' + tempValue + '°C'); res.end(JSON.stringify({"temp": tempValue})); }); temp.stderr.on('data', function () { res.end(JSON.stringify({"temp":"Unavailable"})); });
内容的提问来源于stack exchange,提问作者user9541267
相关产品推荐
相关产品推荐

