Flow 和全局变量
Flow 和全局变量
本节深入介绍 Node-RED 的 Flow 和 Global 变量的使用。学习完成后,您将能够:
- 区分 Flow 变量和 Global 变量的适用场景
- 在多个 Flow 之间共享数据
- 使用 Global 变量实现系统级状态管理
- 管理变量的生命周期和并发安全
Flow Variables
Section titled “Flow Variables”// Flow 变量:同 Tab 内的所有节点共享
// 写入(在任意节点中)flow.set("threshold", 30);flow.set("deviceList", ["SENSOR-01", "SENSOR-02"]);flow.set("config", { location: "Factory A", interval: 5000});
// 读取var threshold = flow.get("threshold") || 25;var devices = flow.get("deviceList") || [];var config = flow.get("config") || {};典型使用场景
Section titled “典型使用场景”场景 1: Flow 级别配置
// 在一个 Tab 中,所有节点共享配置
// 初始化节点(注入节点触发一次)flow.set("tempThreshold", 30);flow.set("humThreshold", 70);flow.set("checkInterval", 5000);
// 数据处理器var tempThreshold = flow.get("tempThreshold");var humThreshold = flow.get("humThreshold");
if (msg.payload.temperature > tempThreshold) { msg.alert = "Temperature exceeded threshold";}return msg;场景 2: Flow 内状态共享
// Function A: 接收数据并存储var count = flow.get("messageCount") || 0;count++;flow.set("messageCount", count);
// Function B: 读取统计信息var totalCount = flow.get("messageCount") || 0;msg.payload = { totalMessages: totalCount, status: "running"};return msg;Global Variables
Section titled “Global Variables”// Global 变量:所有 Tab 和节点共享
// 写入global.set("systemTime", Date.now());global.set("systemStatus", "online");global.set("deviceRegistry", {});
// 读取var sysTime = global.get("systemTime");var status = global.get("systemStatus");var devices = global.get("deviceRegistry") || {};典型使用场景
Section titled “典型使用场景”场景 1: 系统级状态管理
// 在 On Start 中初始化系统状态global.set("system", { startTime: Date.now(), version: "1.2.0", mode: "production", status: "running", uptime: 0});
// 状态监控节点var system = global.get("system");system.uptime = Math.floor((Date.now() - system.startTime) / 1000);system.lastActivity = Date.now();global.set("system", system);
msg.payload = system;return msg;场景 2: 设备注册表管理
// 在所有 Flow 中共享设备列表var registry = global.get("deviceRegistry") || {};
// 注册新设备var deviceId = msg.payload.device || msg.topic;if (deviceId && !registry[deviceId]) { registry[deviceId] = { id: deviceId, firstSeen: Date.now(), type: msg.payload.type || "unknown", status: "active" }; global.set("deviceRegistry", registry); node.log("New device registered: " + deviceId);}
// 更新设备状态if (registry[deviceId]) { registry[deviceId].lastSeen = Date.now(); registry[deviceId].status = "active"; global.set("deviceRegistry", registry);}场景 3: 跨 Flow 数据共享
// Flow A (数据采集): 存储最新传感器数据global.set("latestTemp", 25.3);global.set("latestHum", 68.2);
// Flow B (告警): 读取并检查var latestTemp = global.get("latestTemp") || 0;if (latestTemp > 30) { // 触发告警 msg.payload = { alert: "high_temperature", value: latestTemp }; return msg;}return null; // 温度正常,不触发告警Variables Lifecycle Management
Section titled “Variables Lifecycle Management”// 方式 1: 在 On Start 中初始化// 在 Function 节点的 On Start 代码中:if (!flow.get("initialized")) { flow.set("config", { /* ... */ }); flow.set("thresholds", { /* ... */ }); flow.set("initialized", true); node.log("Flow variables initialized");}
// 方式 2: 延迟初始化(读取时)function getConfig() { var config = flow.get("config"); if (!config) { config = { threshold: 30, interval: 5000, debug: false }; flow.set("config", config); } return config;}// 定期清理过期的全局变量var cleanup = function() { var registry = global.get("deviceRegistry") || {}; var now = Date.now(); var TIMEOUT = 3600000; // 1 小时
for (var id in registry) { if (now - registry[id].lastSeen > TIMEOUT) { registry[id].status = "offline"; node.log("Device offline: " + id); } }
global.set("deviceRegistry", registry);};
// 每小时执行一次清理setInterval(cleanup, 3600000);作用域选择指南
Section titled “作用域选择指南”| 场景 | 推荐作用域 | 原因 |
|---|---|---|
| 节点内部计数器 | Node Context | 最小作用域 |
| Tab 内配置参数 | Flow Context | 模块共享 |
| 跨 Flow 状态 | Global Context | 全局访问 |
| 设备注册表 | Global Context | 需要全局访问 |
| 敏感配置 | Flow Context | 限制作用域 |
// 在 Function 节点中,同一时刻只处理一个消息// 但多个 Flow 可能同时访问同一个 Global 变量
// ✅ 安全操作var count = global.get("count") || 0;count++;global.set("count", count);
// ❌ 避免的操作(可能导致计数错误)// global.set("count", global.get("count") + 1);Common Customer Questions
Section titled “Common Customer Questions”Q1: Flow 变量和 Global 变量的性能差异?
Section titled “Q1: Flow 变量和 Global 变量的性能差异?”A: 性能差异不大。主要区别是作用域范围。优先使用更小的作用域(Node < Flow < Global)。
Q2: 如何在多个 Node-RED 实例间共享变量?
Section titled “Q2: 如何在多个 Node-RED 实例间共享变量?”A: 使用外部队列或数据库(如 Redis)。不推荐通过 Global 变量在多实例间共享。
Q3: 变量命名有什么规范?
Section titled “Q3: 变量命名有什么规范?”A: 建议使用 camelCase 命名,加上前缀区分作用域:
flow_或f_开头:Flow 变量g_开头:Global 变量cfg_开头:配置类型变量
Summary
Section titled “Summary”- Flow 变量: 同 Tab 内共享,适合模块级数据
- Global 变量: 全局共享,适合系统级管理
- 最小作用域原则:优先使用更小的作用域
- 生产环境需要配置 context 持久化
- 合理的初始化和清理策略确保数据一致性