You need to enable JavaScript to run this app. 使用Javascript与Express时为何设置全局变量后仍输出undefined?
优惠活动
大模型
产品
解决方案
定价
更多

使用Javascript与Express时为何设置全局变量后仍输出undefined?

问题根因

你遇到的price始终为undefined的问题,本质来自三个逻辑漏洞:

  • 你定义了getData异步取数函数,但全程没有调用这个函数,代码里没有任何触发取数的逻辑,price从声明后就一直保持未赋值的初始状态,根本不会被修改。
  • 同步代码的执行优先级远高于异步操作:哪怕你主动调用了getData,后面紧跟着的console.log(price)会先执行,此时接口请求还在网络等待阶段,代码还没跑到price = data.c这一行,打印出来的自然是未赋值的初始值。
  • 逻辑放置的位置不符合Express的运行流程:你把模板渲染的绑定逻辑放在了服务启动阶段,就算你真的在启动时拉到了一次价格,后续所有请求拿到的都是服务启动那一刻的旧值,甚至如果取数失败,传给模板的就是未定义的空值。
修正方案

根据你的实际业务需求,选对应的实现即可,不需要依赖全局变量存临时值:

方案1:每次访问首页时拉取最新接口数据(推荐)

这是最符合Express路由设计的写法,不会出现脏数据、时序错位的问题:

const express = require("express");
const app = express()
const fetch = require("node-fetch");

app.set('view engine', 'ejs');
app.use(express.static('Public'));

// 给路由处理函数加async,支持await等待异步请求完成
app.get('/', async function (req, res) {
    try {
        const url = "你的带密钥的接口地址";
        // 等待接口返回后再继续执行
        const response = await fetch(url);
        const data = await response.json();
        const price = data.c;
        // 拿到有效数据后再传给EJS模板渲染
        res.render('index', { price })
    } catch (error) {
        // 捕获接口异常,避免服务因为未处理的Promise rejection崩溃
        res.status(500).send("数据加载失败,请稍后重试")
    }
});

app.listen(3000);

方案2:服务启动时拉取一次数据,全局复用

如果你的业务场景是只需要服务启动时拉一次价格,后续所有请求都用这个固定值,那必须等取数完成后再启动服务:

const express = require("express");
const app = express()
const fetch = require("node-fetch");

app.set('view engine', 'ejs');
app.use(express.static('Public'));

// 用let替代旧的var,避免变量提升带来的不可预期问题
let price;
const url = "你的带密钥的接口地址";

async function bootStrap() {
    // 启动流程第一步:先完成接口取数
    const response = await fetch(url);
    const data = await response.json();
    price = data.c;
    // 取数完成后再启动HTTP服务,此时price已经是有效值
    app.listen(3000, () => {
        console.log("服务启动完成,当前价格:", price)
    });
}

app.get('/', function (req, res) {
    // 因为服务是在price赋值完成后才启动的,这里拿到的price一定是有效状态
    res.render('index', { price })
});

// 必须主动调用启动函数,整个流程才会跑起来
bootStrap()
额外注意点
  • 你代码里的const JSON = require("JSON")属于冗余依赖:Node.js运行环境自带全局JSON对象,不需要额外引入这个包,这行代码可以直接删除,避免不必要的包体积开销。
  • 验证变量赋值状态时,一定要把console.log放在await取数完成的代码块内部,放在外部的同步位置永远打印不到异步赋值后的最终值。
  • 尽量不要用全局变量存储请求级的临时数据:Express服务是并行处理多用户请求的,全局变量的状态会被所有请求共享,很容易出现请求间数据覆盖、拿到脏值的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 23:45:03