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

无数据库时Node.js主进程与Express路由共享数据的架构设计

无数据库场景下的Node.js设备数据管理方案

核心思路:封装独立的状态管理模块

把设备数据的读写、持久化逻辑全部集中到一个独立模块,让主进程、Express路由都通过这个模块操作数据,替代直接传递对象引用的方式,实现解耦和统一管控。


1. 实现数据状态模块(deviceStore.js)

这个模块是唯一的数据入口,负责初始化、读写、持久化所有设备数据:

const fs = require('fs').promises;
const path = require('path');

// 内存中的设备数据(仅模块内部可直接修改)
let deviceData = [];
const STORAGE_FILE = path.join(__dirname, 'devices-backup.json');

// 从外部API加载初始数据,失败则尝试读本地备份
async function initFromAPI(apiUrl) {
  try {
    const res = await fetch(apiUrl);
    deviceData = await res.json();
    await saveToDisk(); // 初始化后立即存盘
  } catch (apiErr) {
    console.error('API拉取失败:', apiErr);
    // 降级加载本地备份
    try {
      const savedStr = await fs.readFile(STORAGE_FILE, 'utf8');
      deviceData = JSON.parse(savedStr);
    } catch (diskErr) {
      console.error('无本地备份可用:', diskErr);
    }
  }
}

// 获取设备数据(返回副本,避免外部直接篡改内存数据)
function getDevices() {
  return JSON.parse(JSON.stringify(deviceData));
}

// 修改设备数据:通过传入修改函数,在模块内部执行更新
function updateDevices(handleUpdate) {
  // 基于当前数据生成新数组,保证操作的原子性
  deviceData = handleUpdate([...deviceData]);
}

// 将内存数据写入磁盘
async function saveToDisk() {
  try {
    await fs.writeFile(STORAGE_FILE, JSON.stringify(deviceData, null, 2));
  } catch (err) {
    console.error('存盘失败:', err);
  }
}

// 启动定时存盘任务(默认30秒一次)
function startAutoSave(intervalMs = 30000) {
  setInterval(saveToDisk, intervalMs);
}

module.exports = {
  initFromAPI,
  getDevices,
  updateDevices,
  startAutoSave,
  saveToDisk
};

2. 主进程启动流程(index.js)

主文件只负责初始化数据、启动定时任务、启动服务器,不直接操作数据:

const { initFromAPI, startAutoSave } = require('./deviceStore');
const startExpress = require('./server');

async function bootstrap() {
  // 1. 加载初始设备数据
  await initFromAPI('https://your-external-api/devices');
  
  // 2. 启动自动存盘
  startAutoSave();
  
  // 3. 启动Express服务器
  await startExpress();
}

bootstrap();

3. Express服务器与路由集成

server.js:只负责服务器初始化,不处理数据逻辑

const express = require('express');
const deviceRoutes = require('./routes/devices');

const app = express();
app.use(express.json());

// 挂载路由,路由直接调用状态模块
app.use('/api', deviceRoutes);

async function startServer() {
  return new Promise(resolve => {
    const server = app.listen(3000, () => {
      console.log('服务器运行在3000端口');
      resolve(server);
    });
  });
}

module.exports = startServer;

routes/devices.js:通过状态模块处理请求

const express = require('express');
const { getDevices, updateDevices, saveToDisk } = require('../deviceStore');
const router = express.Router();

// GET 获取设备列表
router.get('/devices', (req, res) => {
  res.json(getDevices());
});

// POST 更新指定设备
router.post('/devices/:id', (req, res) => {
  const targetId = req.params.id;
  const updates = req.body;

  updateDevices(currentDevices => {
    return currentDevices.map(device => {
      if (device.id === targetId) {
        return { ...device, ...updates };
      }
      return device;
    });
  });

  // 可选:修改后立即存盘(如果需要强一致性)
  saveToDisk().catch(err => console.error('更新后存盘失败:', err));

  res.json({ msg: '设备已更新' });
});

// POST 新增设备
router.post('/devices', (req, res) => {
  const newDevice = req.body;
  updateDevices(currentDevices => [...currentDevices, newDevice]);
  res.status(201).json(newDevice);
});

module.exports = router;

方案优势

  • 解耦清晰:数据逻辑完全独立,主进程、路由只做调用,后续改存储方式(比如加数据库)只需要修改deviceStore.js
  • 数据安全:通过返回副本、内部执行修改,避免外部直接篡改内存数据,防止意外副作用
  • 一致性保障:定时存盘+可选即时存盘,保证内存数据和磁盘备份同步,进程重启后能恢复最近状态
  • 扩展性强:后续加数据校验、操作日志、缓存逻辑,都可以在状态模块里扩展,不影响其他代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:15:51