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

Express中fetch调用API后EJS模板变量未更新问题

问题原因

你遇到的是典型的异步调用时序错误。data()是声明为async的异步函数,内部fetch请求API需要等待网络响应才能更新myStatePopulation变量,但你在POST路由中调用data()后没有等待异步操作执行完成,就立刻执行res.redirect("/")触发GET路由渲染页面。此时页面渲染时API请求还没返回,myStatePopulation还停留在旧值,等控制台打印出正确人口数的时候,页面早就渲染结束了,自然拿不到更新后的值。
另外你把州、年份、人口存在全局变量里的写法也有问题,多用户同时访问站点时,不同用户的查询数据会互相覆盖。

修复方法

不要用全局变量存储单次查询的状态,POST路由中等待API请求返回结果后,再执行页面渲染逻辑,修复后的服务端代码如下:

/* Requiring NPM packages */
const express = require("express");
const ejs = require("ejs");
const fetch = require("node-fetch");
const bodyParser = require("body-parser");
const _ = require("lodash");

/* Using Express */
const app = express();
const port = 3000;

/* Using Static Files */
app.use(express.static(__dirname + "/public"));

/* Using ejs*/
app.set("view engine", "ejs");

/* Using Body-Parser */
app.use(bodyParser.urlencoded({ extended: true }));

/* Fetching API data 直接返回查询结果,不修改全局变量 */
const fetchPopulation = async (nation, year) => {
  const response = await fetch(
    "https://datausa.io/api/data?drilldowns=State&measures=Population&year=" + year
  );
  const myJson = await response.json();
  const allState = myJson.data;
  const targetState = allState.find((x) => x.State === nation);
  // 增加容错,找不到对应州数据时返回提示
  return targetState ? targetState.Population : "无匹配数据";
};

/* Starting the server */
app.get("/", function (req, res) {
  // 首页默认值直接在渲染时传入,无需全局变量存储
  res.render("index", {
    content: "美国人口查询",
    state: "未选择",
    year: "未选择",
    population: "待查询",
  });
});

/* Posting Data 路由改为async函数,等待API返回后再处理 */
app.post("/", async function (req, res) {
  try {
    if (req.body.stateName && req.body.yearDate) {
      const targetNation = _.capitalize(req.body.stateName);
      const targetYear = Number(req.body.yearDate);
      // 等待API请求完成拿到真实人口数据
      const population = await fetchPopulation(targetNation, targetYear);
      // 拿到数据后直接渲染页面,不需要绕路重定向
      res.render("index", {
        content: "美国人口查询",
        state: targetNation,
        year: targetYear,
        population: population,
      });
    } else {
      console.log("重定向到首页");
      res.redirect("/");
    }
  } catch (err) {
    console.log("数据请求失败: ", err);
    res.status(500).send("人口数据获取失败,请重试");
  }
});

app.listen(port, () => console.log("服务运行在端口 : " + port));

原有EJS模板代码不需要修改即可正常使用。

核心改动说明
  • 移除了全局存储查询状态的nation/year/myStatePopulation变量,避免多用户同时访问时数据串扰
  • POST路由添加async声明,调用API时使用await等待请求完成,确保拿到真实人口数据后再渲染页面,从根源解决异步时序问题
  • 增加了错误捕获和无匹配数据的容错逻辑,接口请求失败、输入州名不存在时不会直接导致服务崩溃
  • 去掉了查询成功后的多余重定向,减少一次不必要的网络请求,页面响应速度更快

内容的提问来源于stack exchange,提问作者Kamran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:24:21