跳转到内容

变量作用域与上下文

变量作用域与上下文

本节介绍 Node-RED 中的变量作用域和上下文管理。学习完成后,您将能够:

  • 理解 Node-RED 的三层作用域(局部/Flow/全局)
  • 使用 context 在不同节点间共享数据
  • 管理上下文数据的生命周期
  • 选择合适的存储位置

Node-RED 提供三种变量作用域:

┌──────────────────────────────────────────────────┐
│ Node-RED │
├──────────────────────────────────────────────────┤
│ Global Context (全局作用域) │
│ ├─ 所有 Tab 和节点可访问 │
│ ├─ 持久化存储 │
│ └─ global.get() / global.set() │
├──────────────────────────────────────────────────┤
│ ┌────────────────────────────────────────────┐ │
│ │ Flow Context (Flow 级别作用域) │ │
│ │ ├─ 同 Tab 内的节点可访问 │ │
│ │ ├─ 持久化存储 │ │
│ │ └─ flow.get() / flow.set() │ │
│ └────────────────────────────────────────────┘ │
├──────────────────────────────────────────────────┤
│ ┌────────────────────────────────────────────┐ │
│ │ Node Context (节点级别作用域) │ │
│ │ ├─ 仅当前节点可访问 │ │
│ │ ├─ 持久化存储 │ │
│ │ └─ context.get() / context.set() │ │
│ └────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
// 仅在当前 Function 节点内有效
// 适合: 节点内部状态、计数器、临时缓存
// 写入
context.set("count", 0);
context.set("readings", []);
// 读取
var count = context.get("count") || 0;
var readings = context.get("readings") || [];
// 更新
count++;
context.set("count", count);
// 同 Tab 下的所有节点共享
// 适合: Flow 级别配置、共享状态
// 在 Function A 中写入
flow.set("threshold", 30);
flow.set("deviceConfig", {
sensor01: { type: "temperature", interval: 5000 },
sensor02: { type: "humidity", interval: 10000 }
});
// 在 Function B 中读取
var threshold = flow.get("threshold") || 25;
var config = flow.get("deviceConfig") || {};
// 所有 Tab 和节点共享
// 适合: 系统配置、全局状态、设备注册表
// 写入全局变量
global.set("systemStatus", "running");
global.set("startTime", Date.now());
global.set("devices", {
"SENSOR-01": { lastSeen: Date.now(), status: "online" },
"SENSOR-02": { lastSeen: Date.now(), status: "offline" }
});
// 读取全局变量
var status = global.get("systemStatus");
var devices = global.get("devices") || {};
// settings.js 中配置
contextStorage: {
default: {
module: "localfilesystem" // 文件系统存储
},
memory: {
module: "memory" // 内存存储(重启丢失)
}
}
# Docker 环境配置
services:
nodered:
image: nodered/node-red:latest
environment:
- NODE_RED_CONTEXT_STORAGE_DEFAULT=localfilesystem
volumes:
- ./nodered/data:/data # 持久化目录
存储方式持久性性能使用场景
Default (内存)重启丢失最快临时数据
localfilesystem文件持久化中等生产环境
Redis外部存储多实例共享
Memory (明确配置)重启丢失缓存数据
// 跟踪设备最后上线时间
var devices = context.global.devices || {};
if (!devices) {
devices = {};
context.global.devices = devices;
}
// 更新设备状态
var deviceId = msg.payload.device || msg.topic;
devices[deviceId] = {
lastSeen: Date.now(),
status: "online",
value: msg.payload.value || msg.payload
};
// 检查离线设备(超过 30 秒未更新)
var now = Date.now();
var offlineDevices = [];
for (var id in devices) {
if (now - devices[id].lastSeen > 30000) {
devices[id].status = "offline";
offlineDevices.push(id);
}
}
msg.payload = {
online_count: Object.keys(devices).length,
offline_count: offlineDevices.length,
offline_devices: offlineDevices
};
return msg;
// 计算滑动窗口平均值
var WINDOW_SIZE = 10;
// 节点作用域 - 存储当前读数
var readings = context.get("readings") || [];
readings.push(msg.payload);
// 保持窗口大小
if (readings.length > WINDOW_SIZE) {
readings.shift();
}
context.set("readings", readings);
// 计算统计
var sum = readings.reduce((a, b) => a + b, 0);
msg.payload = {
current: msg.payload,
average: (sum / readings.length).toFixed(2),
min: Math.min(...readings),
max: Math.max(...readings),
count: readings.length
};
return msg;
// 使用全局变量管理系统配置
// 在初始化节点(On Start)中设置
// On Start 代码:
var config = {
temperature: {
warning: 30,
critical: 40,
unit: "celsius"
},
humidity: {
warning: 70,
critical: 85,
unit: "percent"
},
intervals: {
data_collection: 5000,
dashboard_refresh: 10000
}
};
flow.set("config", config);
global.set("systemName", "Factory IoT Monitor");
global.set("version", "1.2.0");
// 在所有节点中均可访问
// 在其他 Function 中:
var config = flow.get("config");
var threshold = config.temperature.warning;
作用域推荐用途不推荐用途
Node计数器、窗口数据配置参数
Flow模块配置、共享状态系统级数据
Global系统配置、设备注册表临时变量

Q1: 重启后 context 数据会丢失吗?

Section titled “Q1: 重启后 context 数据会丢失吗?”

A: 如果使用默认(内存)存储,重启会丢失。生产环境应配置 localfilesystem 或 Redis 持久化存储。

A: 没有硬性限制,但建议保持在合理范围(数百 KB 以内)。大量数据建议存储到外部数据库。

Q3: 如何在多个 Node-RED 实例间共享 context?

Section titled “Q3: 如何在多个 Node-RED 实例间共享 context?”

A: 使用 Redis 作为 context 存储后端,或多个实例连接同一数据库。

推荐做法:

  • 最小作用域原则:优先使用 node context
  • 生产环境配置持久化存储
  • 定期清理不再使用的 context 变量
  • 使用有意义的变量名
  • 初始化时设置默认值

避免做法:

  • 滥用全局变量
  • 存储大量数据到 context
  • 不设置持久化存储
  • 变量名冲突(尤其是在全局作用域)
  • 存储敏感信息(如密码)
  1. Node-RED 提供三层作用域:Node/Flow/Global
  2. Node context 适合节点内部状态
  3. Flow context 适合模块级数据共享
  4. Global context 适合系统级数据和配置
  5. 生产环境必须配置 context 持久化