Node-RED:Function 节点与变量使用范围笔记
- 代码开发
- 2025-11-23
- 464热度
- 0评论
一、Function 节点的代码运行环境
Node-RED是一个物联网可视化编程工具,用于事件驱动应用程序的低代码编程。
Node-RED 的 Function 节点运行在 Node.js 的沙盒环境中,它不是一个完整的 JavaScript 文件,而是 Node-RED 在运行时将你的代码嵌入到一个安全沙盒中执行。
Node-RED 的函数( Function )节点用于编写 JavaScript 代码,对传入的数据进行处理,然后返回多条消息,以使流程继续执行。传入的消息一般以对象形式表示,其名称为
msg,通常都会包含一个msg.payload属性,用来保存消息的主体内容。
Function 节点中涉及的变量大致可分为三类:
- 局部变量(Function 内部变量)
- 消息变量(msg)
- 上下文变量(flow / global / env)
参考:https://nodered.com.cn/docs/user-guide/
二、局部变量(Function 内部)
1. 定义方式
在 Function 节点内部使用以下方式定义局部变量:
let a = 10;
const b = "hello";
var c = true; // 可用,但不推荐
2. 三种变量的区别
| 定义方式 | 作用域 | 是否可重复赋值 | 是否提升(Hoist) | 是否推荐 |
|---|---|---|---|---|
| let | 块级作用域 | ✔ 是 | ❌ 不提升 | ⭐ 强烈推荐 |
| const | 块级作用域 | ❌ 否(引用不可变) | ❌ 不提升 | ⭐ 推荐(常量) |
| var | 函数级作用域 | ✔ 是 | ✔ 会变量提升 | ❌ 不推荐 |
示例:
let count = 0; // 最常用
const PI = 3.14; // 常量
3. 特点
- 每次 Function 节点执行时重新创建
- 执行结束后销毁
- 不会保存状态(要保存状态必须用 flow/global)
- 只在当前 Function 内有效
4. 使用场景
- 一次性计算、临时变量
- 对 msg 数据做加工处理
- 内部函数调用时的参数变量
三、消息变量:msg
1. 传递方式
Node-RED 的所有节点都是处理 msg 对象:
msg.payload = 123;
return msg;
2. 特点
- 通过节点链路连续传递
- 任意节点都可以读写 msg 的字段
- 整条链路结束后 msg 数据消失
- 典型用途:流程间传递数据、状态、标识
3. 修改 msg 的方式
msg.payload = msg.payload + 1;
msg.topic = "sensor";
msg.time = Date.now();
4. 典型使用场景
- 传递传感器数据
- 提供给 UI、MQTT、HTTP 等后续节点
- 控制逻辑的条件判断值
四、flow 变量(当前流程范围共享)
1. 设置和读取
flow.set("counter", 1);
let count = flow.get("counter");
2. 特点
- 一个 Tab(Flow 页)内所有节点可共享
- 默认不持久化(可配置 persistent storage)
- 类似“流程级全局变量”
3. 使用场景
- 滚动计数器
- 状态机
- 中间缓存数据
五、global 变量(全局共享)
1. 使用方法
global.set("token", "ABCD");
let t = global.get("token");
2. 特点
- 所有流程的所有节点都能访问
- 默认同样不持久化
- 用于系统级状态或配置
3. 应用示例
- API 密钥
- 登录状态
- 全系统共享的缓存
六、env 变量(环境变量)
1. 获取方式
let port = env.get("API_PORT");
2. 特点
- 可在 Node-RED 菜单中配置
- 只能读取,不能写入
- 常用作配置项(端口、路径、设备 ID)
七、Function 节点本身的函数能力
Function 节点 == 一个带输入输出的“微型 JS 函数”。
1. 输入参数:msg
Function 节点收到的每一条消息会自动作为 msg 对象传入:
msg.payload—— 主体内容- 你可以添加、修改、删除
msg中的任意属性
Function 的输入永远是 msg:
let val = msg.payload;
2. 函数返回值return(输出行为)
Function 节点最终要 决定是否输出消息,以及输出什么消息。
✅(1)返回 单个 消息对象
return msg;
✅(2)返回 多个 消息(用于多路输出)
return [msg1, msg2];
✅(3)返回数组嵌套(对应多个输出端口)
return [
[msgA, msgB], // 第 1 个输出端口
null, // 第 2 个输出端口无输出
[msgC] // 第 3 个输出端口
];
❌(4)返回 null 或不返回 —— 停止消息继续向下流动阻断输出
return null;
// 或者 simply 不写 return
这样可以让消息 “被吞掉”,常用于:
- 条件过滤
- 错误数据阻断
- 控制流程不继续执行
3. 内部自定义函数(局部函数)
可以在 Function 内声明自己的函数:
function add(a, b){
return a + b;
}
msg.sum = add(2, 3);
return msg;
也可以使用箭头函数:
const double = x => x * 2;
msg.payload = double(msg.payload);
return msg;
4. 错误处理(内置 node 对象)
报错并停止流程
node.error("无效数据", msg);
return null;
使用 try/catch
try {
msg.json = JSON.parse(msg.payload);
} catch(e){
node.error("JSON 解析失败: " + e.message, msg);
return null;
}
return msg;
5. 调试输出(node.warn / node.log)
node.warn("调试信息");
node.log("普通日志");
八、典型综合示例(函数 + 局部变量 + flow/global/msg)
// 局部变量
let raw = msg.payload;
// 自定义函数
const convert = v => v * 2;
// 使用 flow 作为计数器
let count = flow.get("count") || 0;
count++;
flow.set("count", count);
// 使用 global 存储系统时间
let start = global.get("sysStartTime");
// 环境变量
let port = env.get("API_PORT");
// 输出结果
msg.result = convert(raw);
msg.count = count;
msg.start = start;
msg.port = port;
return msg;
九、常见错误与注意事项
1. ❌ 将状态存在局部变量(无效)
let count = 0; // 每次执行都会重置
应使用:
let count = flow.get("count") || 0;
2. ❌ 忘记 return msg
msg.payload = 10;
// 没有 return → 后续节点收不到数据
必须:
return msg;
3. flow/global 默认不持久化
如果希望 Node-RED 重启后仍保留数据,需要在 settings.js 中配置:
contextStorage: {
default: {
module: "localfilesystem"
}
}
十、变量作用范围总结表
| 类型 | 作用范围 | 生命周期 | 可跨节点 | 是否可持久化 | 用途 |
|---|---|---|---|---|---|
| 局部变量 | 当前 Function 内 | 每次执行重建 | ❌ | ❌ | 临时计算 |
| msg | 节点链路中传递 | 链路结束即消失 | ✔ | ❌ | 节点间传输数据 |
| flow | 当前 Tab 所有节点 | Node-RED 运行期间 | ✔ | ✔(可配置) | 状态机 / 缓存 |
| global | 全流程所有节点 | Node-RED 运行期间 | ✔ | ✔(可配置) | 全局配置 |
| env | 环境级 | Node-RED 运行期间 | ✔ | ✔ | 配置项 |