错误处理

虽然创建在一切正常时能正确运行的流程很容易,但考虑可能出现的问题也很重要。

例如,如果流程需要与外部数据库或API交互,当它停止响应请求时会发生什么?或者如果MQTT节点与代理的连接断开会怎样?

在任何应用程序中,错误处理都至关重要,以确保这类事件得到妥善处理。处理错误的含义取决于应用程序的需求。您可能希望重试失败的操作,或触发单独的警报,或者该错误可能完全是预期事件,只是应用程序逻辑的另一部分。

Node-RED 提供了两种方式让节点报告错误。它既可以仅将消息写入日志,也可以通知运行时错误并触发流程。

如果错误仅写入日志,您将在调试侧边栏和日志输出中看到该消息,但无法创建流程来处理它。这些是不可捕获的错误

如果它确实正确通知了运行时,那么这是一个可捕获的错误,可用于触发错误处理流程。

还有第三种错误可能导致Node-RED运行时关闭。这些uncaughtException错误无法在流程中处理,通常由节点中的bug引起。

本指南将更详细地描述这些错误类型,并展示如何处理它们。同时探讨如何利用节点的状态事件来创建处理意外事件的流。

记录错误日志

当节点记录错误时,它会在调试侧边栏中显示。

Error message in the Debug sidebar

调试侧边栏中的错误信息

这里显示错误信息、错误发生的日期/时间以及记录错误的节点。与其他调试消息一样,将鼠标悬停在其上会在工作区中高亮显示对应节点。如果该节点不在当前视图中,点击顶部角落的节点名称即可在工作区中显示它。

可捕获的错误

如果某个节点向运行时报告错误,则可以使用Catch节点创建处理该错误的流程。

Catch node

捕获节点

如果错误被Catch节点捕获,它不会被记录到Debug侧边栏。

Catch节点发送的消息将是报告错误的节点提供的消息。该消息将设置一个error属性,提供有关错误的信息:

{
    "topic": ...,
    "payload": ...,
    "error": {
        "message": "An error",
        "source": {
            "id": "2e25823d.fa3f7e",
            "type": "function",
            "name": "My Function",
            "count": 1
        }
    }
}

msg.error 的属性包括:

  • msg.error:
    • message - 错误信息
    • source - information about the node logging the error:
      • id - 源节点ID
      • type - 源节点的类型
      • name - 源节点的名称(如果已设置)
      • count - 表示当前节点抛出消息的次数。 该属性被运行时用于检测陷入循环的消息 - 即消息被传递回源节点后再次记录错误,如此循环。 运行时将允许消息循环9次,之后会记录另一个无法捕获的错误来中断循环。删除此属性将禁用该检查。

如果节点报告错误时消息已包含msg.error属性,则该属性将被移至msg._error

默认情况下,Catch节点被配置为由编辑器中同一标签页上的所有节点触发,但也可以配置为仅针对该标签页上的特定节点。

如果在同一个标签页中有两个Catch节点,并且它们都指向同一个节点,那么该节点报告的任何错误都会同时触发这两个Catch节点。

如果Catch节点被配置为由所有节点触发,它还可以设置为仅捕获未被其他Catch节点处理的错误。 这样您就可以创建针对特定节点的错误处理流程,同时还能设置一个"兜底"错误处理器来捕获"其他所有未处理的错误"。

子流程中的错误

如果子流程内部记录了一个错误,运行时将首先检查子流程内是否存在任何捕获节点。如果子流程内没有捕获节点,错误将向上传播到包含该子流程实例的主流程中。

无法捕获的错误

这些是节点写入日志但未正确通知运行时的错误。 它们无法使用Catch节点处理。

该节点可能提供了处理错误的替代方法。例如,通过更新其状态属性(可以使用状态节点进行监控)。它可能会正常发送消息,但设置一些额外的属性来指示错误。

您可能需要联系该节点的作者,查看是否可以更新以正确记录错误。

uncaughtException 错误

这是一种特定类型的node.js错误,当节点未能正确处理内部错误时可能发生。它们会导致整个Node-RED运行时关闭,因为这是唯一安全的处理方式。

这听起来可能有些极端,但node.js文档是这样描述的:

在未捕获异常后尝试正常恢复,就像在升级电脑时直接拔掉电源线一样。十次中有九次可能没事,但第十次系统就会损坏。

典型原因通常是一个节点启动了异步任务,而该任务遇到了错误。编写良好的节点会为该任务注册错误处理程序,但如果没有处理程序,错误将无法被捕获。

如果遇到此类错误,您应尝试识别是哪个节点引发了错误,并针对该节点提交问题报告。由于错误的异步特性,这并不总是容易做到。

Node-RED日志中提供的堆栈跟踪将提供一些线索,帮助了解触发错误的异步任务的性质,进而可能有助于识别出问题的节点。

处理状态变更

并非所有错误情况都会显示为可被Catch节点捕获的错误事件。例如,MQTT节点失去连接时不会触发错误,但会触发其状态的变化。

正如Catch节点可用于处理错误事件一样,Status节点可用于处理节点状态的变化。

Status节点发送的消息包含status属性,该属性提供了关于状态和触发事件的节点的信息。

{
    "status": {
        "fill": "red",
        "shape": "ring",
        "text": "node-red:common.status.disconnected",
        "source": {
            "id": "27bbb5b1.d3eb3a",
            "type": "mqtt out"
        }
    }
}