流程结构

当你第一次开始使用 Node-RED 时,可能会将所有节点添加到编辑器的同一个标签中。你可能会导入一些其他人分享的示例流程,或构建原型流程来测试不同的功能。

随着时间的推移,这可能会导致节点和电线的杂乱,使得很难找到流程的特定部分。

在任何开发项目开始时,认真考虑如何构建流程可以帮助保持其组织性,并使其更易于维护。

在 Node-RED 中组织流程的主要方法是通过在编辑器中将它们分隔到多个标签上。有几种不同的策略可以做到这一点。

如果你能识别出应用程序的独立逻辑组件,可以考虑将它们放在单独的标签中。

对于一个家庭自动化应用程序,可以将每个房间的流程逻辑放在单独的标签上,以反映物理空间。或者你可能希望根据功能分隔流程 — 比如所有与照明相关的流程放在一个标签上,供暖流程放在另一个标签上。

如果你正在构建一个 HTTP API 后端,每个标签可以代表 API 访问的不同类型的资源。

目标应该是使从头到尾“阅读”一个独立流程变得容易。保持在单个标签上可以帮助实现这一点。

另一个考虑是你是否与其他开发人员在同一个 Node-RED 应用程序上合作。如果它们在单独的标签上,那么管理合并更改会容易得多。如果你有不同角色或专业的开发人员,考虑这可能如何影响你的流程的组织方式。

创建可重用的流程

在构建你的流程时,你可能会发现一些想要在多个地方重用的公共部分。你应该避免在流程中多个地方散布这些公共部分,因为它们变得更难维护 — 你最终会拥有多个地方来应用修复,可能会轻易忽视某一个。

Node-RED 提供了两种创建可重用流程的不同方法 — 链接节点和子流程。

链接节点

链接节点

链接节点 让你创建一个可以在编辑器标签间跳转的流程 — 它们从一个流程的末尾添加一根虚拟电线到另一个流程的开始。

子流程

子流程

子流程 让你在调色板中创建一个节点,其内部实现被描述为一个流程。你可以在需要常规节点的任何地方添加子流程的新实例。

这两种方法之间有一些重要区别。链接节点不能用于流程中间,消息在链接上通过,然后在另一个流程完成时返回。它们只能用于开始或结束一个流程。它们也可以与超过一个其他链接节点连接。这使你能够向多个其他流程传递消息,或者让多个流程将消息传递到单个流程。它们可以在单个标签内使用,帮助流程在工作空间中扩展,而不会有许多电线从右到左交叉。

子流程表现为常规节点,因此可以在流程的任何点使用。然而,子流程的每个实例都是独立的。子流程内部的任何流程上下文将局限于单个实例。如果子流程创建与远程系统的连接,每个实例将创建自己的连接。

自定义子流程

在创建子流程时,你可能希望能够以某种方式自定义其行为。例如,更改其发布的 MQTT 主题。

实现这一目标的一种模式是在每个传递给子流程的消息上设置 msg.topic。但这需要在每个子流程实例前添加一个更改节点,以设置所需的值。

更简单的方法是使用子流程属性。这些是可以在子流程实例上设置的属性,并在子流程内部出现为环境变量。

在 MQTT 示例中,你可以先将节点配置为发布到 ${MY_TOPIC}

通过环境变量设置的 MQTT 主题

通过环境变量设置的 MQTT 主题

添加子流程属性

添加子流程属性

然后将 MY_TOPIC 添加为子流程属性。

当用户编辑单个实例时,他们可以为该实例提供 MY_TOPIC 的自定义值。

自定义子流程实例属性

自定义子流程实例属性

这种模式可以应用于任何允许你直接输入值的节点配置字段。目前,它不适用于暴露为复选框或其他自定义 UI 元素的字段。

管理状态信息

另一个考虑是如何在你的流程中管理任何状态信息。例如,保持通过流程的消息数量统计,或外部传感器的当前状态。

Node-RED 提供了上下文系统来管理运行时的状态。上下文可以局限于相同的标签、子流程或全局可用。

如果某个状态信息仅对特定标签上的节点所需,则应使用流范围而不是全局范围。你还应小心选择上下文变量名称 — 确保它们具有描述性且易于识别。

另一个选项是在 Node-RED 之外管理状态 — 比如使用保留的 MQTT 消息,或某种数据库。这些选项确实增加了外部依赖关系,并且没有上下文集成得那么方便,但它们也可以与上下文并行使用,而不是完全替代。例如,在你希望在多个 Node-RED 实例之间共享状态信息,或在 MQTT 的情况下,能够在值变化时触发流程。

针对不同平台自定义流程

环境变量可以在 Node-RED 中更广泛地使用,以创建可以针对不同平台自定义的流程,而无需进行手动更改。

例如,你可能有一个计划在多个设备上运行的流程,但每个设备应该订阅其自己独特的 MQTT 主题。

与以上子流程示例一样,你可以配置 MQTT 节点发布到 ${MY_TOPIC},然后在运行 Node-RED 之前将其设为环境变量。这允许设备特定的自定义与应适用于所有设备的流程分别维护。

同样的方法可以用于流程可能在不同操作系统上运行的情况 — 在这种情况下,流程使用的文件路径可能因操作系统而异。

Inject 和 Change 节点可以使用 TypedInput 中的“env”选项访问环境变量。Function 节点可以使用 env.get() 函数。

错误处理

Node-RED 提供了 Catch 和 Status 节点作为构建可以响应错误的流程的方法。有关它们如何使用的更多信息,请参考 用户指南

由于 Catch 节点和它所针对的节点之间没有直接的视觉关联,因此你应考虑如何定位它们,以保持流程的可读性。

将它们放置在与其对应的流程部分靠近的位置可以有所帮助,但你应该注意不要导致流程过于拥挤。

另一种方法是将所有错误处理流程分组在主要流程下 — 使“良好”路径与错误路径明显不同。

给你的 Catch 节点一个清晰的名称也非常重要,以帮助轻松识别它们旨在处理的场景。

无论你选择哪种方法,都要尽量在不同流程间保持一致性。