You need to enable JavaScript to run this app. 如何实现Node.js服务定时自动重启 每10秒刷新API拉取的最新数据
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Node.js服务定时自动重启 每10秒刷新API拉取的最新数据

温湿度Node.js服务10秒刷新数据的实现方案

核心判断

你提到的两种实现方向都是走了弯路:既不需要把全量app.js代码封装靠循环定时重启实现刷新,也不需要引入crontab这类系统级调度工具,纯Node.js内置能力配合现有forever工具,就能稳定实现需求。

你当前代码存在的基础问题

  • 末尾定义的匿名async函数没有被实际调用:你现在的代码只是写完了函数逻辑,没有加执行括号触发运行,直接启动的话不会有任何服务启动、API调用的动作
  • 数据拉取逻辑和服务启动绑死:就算修了函数调用的问题,温湿度数据只会在服务启动的那一刻拉取一次,后续不管服务跑多久,页面展示的永远是启动瞬间的旧值,完全达不到“始终最新”的效果

两种思路的可行性辨析

不推荐:全量代码封装+定时重启

  • 如果你把整个服务逻辑放到setInterval里定时执行,第二次循环就会触发EADDRINUSE端口占用错误——因为express的app.listen是长驻监听逻辑,重复调用会直接报错
  • 定时重启进程的运行开销极高,还会出现用户访问服务时刚好碰到重启断档的问题

完全没必要:crontab系统调度

  • crontab的设计定位是跑独立的一次性离线任务,不适合承载长驻Web服务
  • 跨平台兼容性差,Windows环境没有原生crontab能力,对新手的学习成本很高

推荐的落地实现

核心原则是Web服务长驻只启动一次,数据拉取逻辑独立定时执行:

  1. 把温湿度API的拉取逻辑抽成独立的可重复执行函数
  2. 用全局变量存储最新拉取到的温湿度值,每次拉取完成就更新这个变量
  3. express服务只在启动阶段初始化一次,监听端口的动作永远不重复执行
  4. 服务启动后先立刻拉一次数据,再用setInterval设置10秒的刷新周期,持续更新全局存储的最新值
  5. 做代码变更时的自动重启,直接用forever的文件监听能力实现就行,和数据刷新逻辑完全解耦

优化后的参考代码:

const something = require("some node module");
const express = require("express");
const bodyParser = require("body-parser");

// 初始化全局存储最新数据的变量
let latestData = {
  temperature: null,
  humidity: null
}

// 把拉取数据的逻辑抽成独立函数
async function refreshDeviceData() {
  try {
    const connection = new something({
      email: "email",
      password: "password",
      region: "us",
    });
    const temperatureRes = await connection.getDeviceCurrentTemperature("some ID");
    const humidityRes = await connection.getDeviceCurrentHumidity("some ID");
    // 拉到新数据就覆盖全局变量
    latestData.temperature = temperatureRes.temperature;
    latestData.humidity = humidityRes.humidity;
    console.log(`数据已刷新,当前温度: ${latestData.temperature} °C, 湿度: ${latestData.humidity} %`);
  } catch (err) {
    // 拉取失败不要让整个服务崩掉,打日志就行
    console.log("数据刷新失败,错误信息:", err.message);
  }
}

// 初始化express服务(只执行一次)
const app = express();
app.use(express.static("public"));
app.set("view engine", "ejs");
app.set("views", __dirname + "/views");
app.use(bodyParser.urlencoded({ extended: false }));

app.get("/", (req, res) => {
  // 渲染的时候直接取全局存的最新数据
  res.render("index", { 
    temp: latestData.temperature, 
    hum: latestData.humidity 
  });
});

// 启动服务逻辑
async function startService() {
  // 启动后立刻先拉一次数据,避免刚启动的时候页面是空的
  await refreshDeviceData();
  // 设置10秒周期刷新
  setInterval(refreshDeviceData, 10 * 1000);
  // 启动监听,只执行一次
  app.listen(8080, () => {
    console.log("服务已启动,端口8080");
  });
}

// 真正执行启动函数
startService();

实现细节注意点

  • 所有API调用的逻辑都要加try/catch捕获异常,避免单次调用失败导致整个服务崩溃退出
  • 全局存储的数据量不要设太大,存当前最新的温湿度值就够,避免内存泄漏
  • 不要把express初始化、端口监听的代码放到定时执行的函数里,否则必然触发端口占用报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 01:54:05