You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中API数据需手动刷新才显示的问题求助

问题分析与解决方案

问题根源

你的代码存在异步操作时序错误:https.get是异步请求,当你调用res.redirect('/results')时,API请求还未完成,全局变量temperature、pressure仍未更新。此时跳转到/results路由,渲染的还是旧数据;手动刷新时,之前的异步请求已完成,全局变量被更新,因此能显示正确数据。

另外,用全局变量存储请求数据存在安全隐患,多用户访问时会互相覆盖数据,必须改成请求级别的数据传递。

修复步骤

  1. 移除全局变量,在POST请求内部处理数据,等API请求完成后再渲染结果页(或跳转)
  2. 确保https.get的异步操作完成后再执行响应逻辑,避免时序错误
  3. 处理原生https的分块数据流(data事件可能多次触发,需拼接完整数据)
  4. 增加错误处理,提升用户体验

修复后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:05:27