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

Node.js Express中如何用await/.then处理Logix.js异步导出变量?

解决方案

方案1:导出Promise等待首次数据,结合getter获取最新值

修改Logix.js,通过Promise通知主模块首次数据就绪,同时用getter确保每次访问都是最新的轮询数据:

"use-strict";

const PLC = require("node-logix").default;
PLC.defaultOptions.Micro800 = true;
const comm = new PLC("192.168.0.5");
let arr1 = [];
let interval1 = null;

// 创建Promise,首次获取数据后resolve
const firstDataReady = new Promise((resolve, reject) => {
  comm.on("connect", async () => {
    console.log("PLC connected successful! ");
    try {
      // 先执行一次数据读取,完成后resolve
      const data = await comm.read("SETTINGS", { count: 10 });
      arr1 = data.splice(0);
      resolve(arr1);
      // 启动定时轮询
      interval1 = setInterval(poolData, 1500);
    } catch (err) {
      reject(err);
    }
  });

  comm.on("connect_error", (err) => {
    reject(err);
  });
});

comm.connect().catch(console.error);

comm.on("disconnect", reason => {
  if (interval1) clearInterval(interval1);
  console.log("PLC disconnected reason:", reason);
});

async function poolData() {
  try {
    const data = await comm.read("SETTINGS", { count: 10 });
    arr1 = data.splice(0);
  } catch (err) {
    console.error("读取PLC数据失败:", err);
  }
}

// 导出Promise和实时数据的getter
module.exports = {
  get arr1() {
    return arr1;
  },
  waitForFirstData: () => firstDataReady
};

在index.js中,用async函数等待Promise完成,路由中直接通过getter获取最新数据:

/*Required External Modules*/

const express = require("express");
const path = require("path");
const moduleL = require('./Logix.js');


/*App Variables*/

const app = express();
const port = process.env.PORT || "8000";
let arr1 = [];

// 等待首次PLC数据就绪
(async () => {
  try {
    arr1 = await moduleL.waitForFirstData();
    console.log("首次数据加载完成: " + arr1);
  } catch (err) {
    console.error("PLC连接或数据读取失败:", err);
  }
})();

/*App Configuration*/

app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");
app.use(express.static(path.join(__dirname, "public")));

/*Routes Definitions*/

app.get("/", (req, res) => {
    res.render("index", { title: "Home" });
  });
  
app.get("/user", (req, res) => {
    // 直接获取最新的轮询数据
    res.render("user", { title: "Profile", userProfile: moduleL.arr1 });
});

/*Server Activation*/

app.listen(port, () => {
    console.log(`Listening to requests on http://localhost:${port}`);
  });

方案2:用事件系统实时感知数据更新

如果需要实时响应数据变化,可借助Node的EventEmitter触发更新事件:

"use-strict";

const PLC = require("node-logix").default;
const EventEmitter = require('events');
PLC.defaultOptions.Micro800 = true;
const comm = new PLC("192.168.0.5");
const emitter = new EventEmitter();
let arr1 = [];
let interval1 = null;

comm.on("connect", () => {
  console.log("PLC connected successful! ");
  interval1 = setInterval(poolData, 1500);
});

comm.connect().catch(console.error);

comm.on("connect_error", e => {
  console.log("Fail to connect PLC!");
  emitter.emit('error', e);
});

comm.on("disconnect", reason => {
  if (interval1) clearInterval(interval1);
  console.log("PLC disconnected reason:", reason);
});

async function poolData() {
  try {
    const data = await comm.read("SETTINGS", { count: 10 });
    arr1 = data.splice(0);
    // 触发数据更新事件,传递最新数据
    emitter.emit('dataUpdated', arr1);
  } catch (err) {
    console.error("读取PLC数据失败:", err);
    emitter.emit('error', err);
  }
}

// 导出getter和事件监听方法
module.exports = {
  get arr1() {
    return arr1;
  },
  on: emitter.on.bind(emitter),
  once: emitter.once.bind(emitter)
};

index.js中监听事件,处理首次和后续数据更新:

/*Required External Modules*/

const express = require("express");
const path = require("path");
const moduleL = require('./Logix.js');


/*App Variables*/

const app = express();
const port = process.env.PORT || "8000";
let arr1 = moduleL.arr1;

// 等待首次数据更新
moduleL.once('dataUpdated', (newData) => {
  arr1 = newData;
  console.log("首次数据加载完成: " + arr1);
});

// 监听后续数据更新
moduleL.on('dataUpdated', (newData) => {
  arr1 = newData;
  console.log("数据已更新: " + arr1);
});

// 监听错误
moduleL.on('error', (err) => {
  console.error("PLC操作出错:", err);
});

/*App Configuration*/

app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");
app.use(express.static(path.join(__dirname, "public")));

/*Routes Definitions*/

app.get("/", (req, res) => {
    res.render("index", { title: "Home" });
  });
  
app.get("/user", (req, res) => {
    res.render("user", { title: "Profile", userProfile: moduleL.arr1 });
});

/*Server Activation*/

app.listen(port, () => {
    console.log(`Listening to requests on http://localhost:${port}`);
  });

核心要点

  • 直接导出变量时,Node模块同步加载会拿到初始空数组,后续变量引用更新无法自动通知主模块,因此需要借助Promise或事件系统实现异步等待。
  • 使用getter可以确保每次访问moduleL.arr1时都获取最新的轮询数据,避免引用失效问题。
  • 方案1适合只需要等待首次数据,后续直接取最新值的场景;方案2适合需要实时响应数据变化的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:47:00