跳转到内容

Function 节点编程

Function 节点编程

本节介绍 Node-RED 中最重要的节点——Function 节点。学习完成后,您将能够:

  • 理解 Function 节点的编程模型
  • 编写 JavaScript 代码处理消息
  • 使用 Function 节点实现数据处理逻辑
  • 掌握消息对象的操作和返回

Function 节点允许用 JavaScript 代码实现自定义数据处理逻辑:

输入: msg (消息对象)
[Function Node: JavaScript 代码]
输出: msg (处理后的消息对象) 或 null (丢弃消息)
// 标准消息对象结构
{
_msgid: "abc123", // 消息唯一 ID
topic: "sensor/temp", // 主题 (可选)
payload: 25.3, // 消息载荷 (核心数据)
data: {/* ... */}, // 自定义属性 (可选)
headers: {/* ... */}, // HTTP 头 (HTTP 相关)
req: {/* ... */}, // 请求对象 (HTTP 相关)
res: {/* ... */} // 响应对象 (HTTP 相关)
}
// 最简单的 Function
// 输入: msg.payload = 25.3
// 输出: msg.payload = "Temperature: 25.3°C"
msg.payload = "Temperature: " + msg.payload + "°C";
return msg;
// 创建新的消息对象
// 输入: msg.payload = {temp: 25.3, hum: 68}
var result = {
temperature: msg.payload.temp,
humidity: msg.payload.hum,
timestamp: Date.now(),
status: msg.payload.temp > 30 ? "warning" : "normal"
};
msg.payload = result;
return msg;
// 条件逻辑
// 输入: msg.payload = 25.3
if (msg.payload > 30) {
msg.payload = {
action: "cooling_on",
reason: "Temperature too high"
};
return msg;
} else if (msg.payload < 15) {
msg.payload = {
action: "heating_on",
reason: "Temperature too low"
};
return msg;
} else {
return null; // 丢弃消息,不触发后续节点
}
// 配置: 设置 2 个输出端口
// 输出 1: 正常数据
// 输出 2: 告警数据
if (msg.payload > 30) {
// 发送到输出 1 (告警)
var alertMsg = { payload: "High temperature alert: " + msg.payload };
// 发送到输出 2 (日志)
var logMsg = { payload: { value: msg.payload, time: Date.now() } };
return [alertMsg, logMsg];
} else {
// 只发送到输出 1
return [msg, null]; // null = 该输出不发送消息
}
// 使用 Promise 处理异步操作
return new Promise((resolve, reject) => {
// 模拟异步 API 调用
setTimeout(() => {
msg.payload = msg.payload * 2;
resolve(msg);
}, 1000);
});
// 使用上下文存储状态
var count = context.get("count") || 0;
count++;
context.set("count", count);
// 访问 Flow 变量
var flowVar = flow.get("config") || {};
flow.set("config", flowVar);
// 访问全局变量
var globalVar = global.get("systemStatus") || {};
global.set("systemStatus", globalVar);
msg.payload = {
count: count,
flowVar: flowVar,
globalVar: globalVar
};
return msg;
// 输入: {temp: 25.123456, hum: 68.987654}
// 输出: {temperature: "25.12°C", humidity: "68.99%"}
var data = msg.payload;
msg.payload = {
temperature: data.temp.toFixed(2) + "°C",
humidity: data.hum.toFixed(2) + "%",
timestamp: new Date().toISOString()
};
return msg;
// 输入: 字符串 JSON
// 输出: 解析后的对象
try {
var jsonData = JSON.parse(msg.payload);
msg.payload = {
deviceId: jsonData.device,
value: jsonData.value,
unit: jsonData.unit
};
return msg;
} catch (e) {
node.error("JSON parse error: " + e.message);
return null;
}
// 累积计算平均值
var readings = context.get("readings") || [];
readings.push(msg.payload);
// 只保留最近 10 个值
if (readings.length > 10) {
readings.shift();
}
context.set("readings", readings);
// 计算平均值
var sum = readings.reduce((a, b) => a + b, 0);
var avg = sum / readings.length;
msg.payload = {
current: msg.payload,
average: avg.toFixed(2),
count: readings.length
};
return msg;
// 1. 使用 node.warn() 输出调试信息
node.warn("Input value: " + msg.payload);
// 2. 使用 node.log() 记录日志
node.log("Processing message from: " + msg.topic);
// 3. 使用 node.error() 输出错误
try {
// 处理逻辑
} catch (error) {
node.error("Error: " + error.message, msg);
}
// 4. 结合 Debug 节点
// 在 Function 节点后连接 Debug 节点
// 可以直接查看返回的消息对象
属性说明示例
Name节点名称”Temperature Converter”
FunctionJavaScript 代码msg.payload *= 2; return msg;
Outputs输出端口数1, 2, 3…
On Start启动时执行的代码初始化变量
On Message消息处理代码主要逻辑

Q1: Function 节点支持哪些 JavaScript 语法?

Section titled “Q1: Function 节点支持哪些 JavaScript 语法?”

A: 支持 ES6+ 语法(箭头函数、模板字符串、Promise、async/await 等)。运行在 Node.js 环境,可用大多数 npm 模块。

A: 每个消息在 Function 节点中执行 JavaScript 代码。简单操作 < 1ms,复杂计算可能 10-100ms。建议避免繁重计算。

A: 使用 Inject 节点发送测试数据,在后续连接 Debug 节点查看输出。也可以在 Function 中使用 node.warn() 输出中间结果。

推荐做法:

  • 保持 Function 代码简洁(< 50 行)
  • 使用 try/catch 处理错误
  • 使用 return null 丢弃不需要的消息
  • 使用 context 存储状态数据
  • 为 Function 节点设置有意义的名称

避免做法:

  • 编写超过 100 行的 Function 代码
  • 忽略错误处理
  • 滥用全局变量
  • 在 Function 中执行阻塞操作
  • 不处理异步操作的错误
  1. Function 节点是 Node-RED 最灵活的数据处理工具
  2. msg 对象是 Flow 中的核心数据载体
  3. 支持单输出和多输出两种模式
  4. context 提供局部/Flow/全局三种作用域存储
  5. node.warn()node.error() 是主要调试手段