在一切正常时,创建能正确工作的流程很容易,但同样需要考虑可能出什么问题。
例如,流程与外部数据库或 API 交互时,对方不再响应请求会怎样?MQTT 节点与消息代理失去连接又会怎样?
任何应用都需要错误处理,才能正确应对这类事件。“处理错误”具体意味着什么,取决于应用要求。你可能希望重试失败的操作、触发单独的告警;也可能这个错误完全在预期之内,只是应用逻辑的一部分。
Node-RED 提供两种方式,让节点报告错误。它可以只向日志写一条消息,也可以将错误通知运行时,从而触发某个流程。
如果错误仅被写入日志,你会在 Debug 侧栏和日志输出中看到消息,但无法创建流程来处理。这类错误是不可捕获的错误。
如果节点正确地通知运行时,该错误便是可捕获的错误,可用于触发错误处理流程。
还有第三类错误,会导致 Node-RED 运行时关闭。这种 uncaughtException 错误无法在流程中处理,是节点中的程序缺陷造成的。
本指南进一步介绍各类错误及其处理方法,也会说明如何利用节点的 Status 事件创建流程,处理意外事件。
记录错误
节点记录错误时,它会出现在 Debug 侧栏中。
Debug 侧栏中的错误消息
官方原图:Debug 侧栏中的错误消息。来源:Node-RED 官方文档
这里显示错误消息、发生日期与时间,以及记录错误的节点。与其他 Debug 消息一样,将鼠标悬停在消息上,会在工作区中高亮对应节点。如果它不在当前视图中,点击消息顶部角落的节点名称,可以在工作区中显示该节点。
可捕获的错误
如果节点将错误通知运行时,可以使用 Catch 节点创建流程来处理。
Catch 节点
官方原图:Catch 节点错误处理流程。来源:Node-RED 官方文档
如果错误被 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:记录错误的节点信息:id:源节点 IDtype:源节点类型name:源节点设置的名称(如果有)count:该消息被该节点抛出的次数。运行时通过此属性检测卡在循环中的消息:消息传回源节点,节点再次记录错误,再传回,以此类推。运行时允许消息循环 9 次,此后记录一个不可捕获的错误,打破循环。删除这个属性就会禁用此检查。
如果节点报告错误时,消息已经有 msg.error 属性,原有属性会被移到 msg._error。
默认情况下,Catch 节点会被编辑器同一标签页中的所有节点触发,也可以配置为只监视该标签页中的指定节点。
如果同一标签页有两个 Catch 节点,而且都监视同一个节点,那么该节点报告的任何错误,都会触发这两个 Catch 节点。
当 Catch 节点被配置为监视所有节点时,还可以设置为仅在错误尚未被另一个 Catch 节点捕获时触发。这样就能为特定节点创建错误处理流程,同时再创建一个负责捕获“其余所有错误”的处理器。
子流程中的错误
如果错误来自子流程内部,运行时会先检查子流程里是否有 Catch 节点。如果没有,错误会向上传播到包含该子流程实例的流程。
不可捕获的错误
这类错误由节点写入日志,但没有正确通知运行时,不能用 Catch 节点处理。
节点可能提供替代处理方式。例如,更新它的状态属性,由 Status 节点监视;也可能正常发送消息,但设置额外属性来表示错误。
你可以联系节点作者,询问是否能更新节点,以正确报告错误。
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"
}
}
}












暂无评论内容