Node.js中API数据需手动刷新才显示的问题求助
问题分析与解决方案
问题根源
你的代码存在异步操作时序错误:https.get是异步请求,当你调用res.redirect('/results')时,API请求还未完成,全局变量temperature、pressure仍未更新。此时跳转到/results路由,渲染的还是旧数据;手动刷新时,之前的异步请求已完成,全局变量被更新,因此能显示正确数据。
另外,用全局变量存储请求数据存在安全隐患,多用户访问时会互相覆盖数据,必须改成请求级别的数据传递。
修复步骤
- 移除全局变量,在POST请求内部处理数据,等API请求完成后再渲染结果页(或跳转)
- 确保
https.get的异步操作完成后再执行响应逻辑,避免时序错误 - 处理原生
https的分块数据流(data事件可能多次触发,需拼接完整数据) - 增加错误处理,提升用户体验
修复后的代码
app.js 优化版
// 移除全局变量,改用请求内局部变量 app.get('/', function(req, res) { res.render('home'); }); // 直接访问/results时重定向到首页 app.get('/results', function(req, res) { res.redirect('/'); }); app.post('/', function(req, res) { const cityName = req.body.cityName; const api_url = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=8bb235e1990db4b5ae16f92e920bad25`; let rawData = ''; https.get(api_url, function(output) { // 拼接分块返回的数据 output.on('data', function(chunk) { rawData += chunk; }); // 数据接收完成后处理 output.on('end', function() { try { const weatherData = JSON.parse(rawData); const temperature = (Number(weatherData.main.temp) - 273.15).toFixed(2); const pressure = Number(weatherData.main.pressure); console.log(`Temperature: ${temperature} °C`); console.log(`Pressure: ${pressure} hPa`); // 直接渲染结果页,避免重定向导致的时序问题 res.render('results', { cityName, pressure, temperature }); } catch (error) { console.error('解析API数据出错:', error); res.render('home', { error: '获取天气数据失败,请检查城市名称' }); } }); // 处理API请求错误 output.on('error', function(error) { console.error('API请求出错:', error); res.render('home', { error: '请求天气API失败,请稍后重试' }); }); }); }); let port = process.env.PORT || 3000; app.listen(port, function() { console.log("服务器已成功启动在端口", port); });
可选优化:用Axios简化异步请求
安装axios(npm install axios)后,代码会更简洁易维护:
const axios = require('axios'); // ...其他路由保持不变 app.post('/', async function(req, res) { try { const cityName = req.body.cityName; const api_url = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=8bb235e1990db4b5ae16f92e920bad25`; const response = await axios.get(api_url); const weatherData = response.data; const temperature = (weatherData.main.temp - 273.15).toFixed(2); const pressure = weatherData.main.pressure; res.render('results', { cityName, pressure, temperature }); } catch (error) { console.error('请求失败:', error); res.render('home', { error: '获取天气数据失败,请检查城市名称' }); } });
results.ejs 保持不变(可保留)
<div class="container"> <div class="card-deck"> <div class="card bg-light mb-3"> <div class="card-header">City</div> <div class="card-body"> <ul> <li><p class="card-text">City Name: <%= cityName %>.</p></li> <li><p class="card-text">Temperature: <%= temperature %> °C.</p></li> <li><p class="card-text">Pressure: <%= pressure %> hPa.</p></li> </ul> </div> </div> </div> </div>
home.ejs 添加错误提示(可选)
<div class="container1 container"> <% if (error) { %> <div class="alert alert-danger" role="alert"> <%= error %> </div> <% } %> <form method="post" action="/"> <div class="brand-logo"></div> <div class="brand-title">WEATHER MONITORING</div> <div class="inputs"> <label>CITY NAME</label> <input autocomplete="off" name="cityName" type="text" placeholder="Mumbai" required /> <button type="submit">CHECK</button> </div> </form> </div>
关键改进点
- 解决异步时序问题:等待API请求完成后再渲染页面,避免提前重定向
- 移除全局变量:使用局部变量存储请求数据,避免多用户数据冲突
- 完善错误处理:捕获API请求和数据解析错误,给用户友好提示
- 数据格式化:温度保留两位小数,提升显示体验
内容的提问来源于stack exchange,提问作者Yolo-cell-hash
相关产品推荐
相关产品推荐

