【发布时间】:2020-10-02 05:19:27
【问题描述】:
我想将 Shiny 模块包装成一种“try catch”,以防止它以任何意想不到的方式崩溃。 Module 代表shinydashboard 选项卡之一,因此在其中一个组件发生故障后,该应用程序仍然可用。
我知道使用req 函数在单个错误后不停止应用程序的可能性(例如在this 帖子中提出)但这里的目标是通过减少用户在相当复杂的错误中的成本来实现快速获胜有大量技术债务的应用程序。
预期行为:显示模块崩溃模式后,用户仍然可以使用该应用程序。
可重现的例子:
library(shiny)
counterButton <- function(id, label = "Counter") {
ns <- NS(id)
tagList(
actionButton(ns("button"), label = label),
verbatimTextOutput(ns("out"))
)
}
counter <- function(input, output, session) {
count <- reactiveVal(0)
observeEvent(input$button, {
count(count() + 1)
stop("Test observeEvent error")
})
output$out <- renderText({
count()
})
count
}
ui <- fluidPage(
counterButton("counter1", "Counter #1")
)
server <- function(input, output, session) {
tryCatch({
callModule(counter, "counter1")
}, error = function(err) {
showNotification(paste("Error: ", err$message), type = "error")}
)}
shinyApp(ui, server)
我找到了一个部分解决方案(请参阅here),它确实有效,但它涉及应用程序模块代码的更改,这对我来说并不总是可以做到:
tryObserveEvent <- function(eventExpr, handlerExpr, ...) {
eventExpr <- substitute(eventExpr)
handlerExpr <- substitute(handlerExpr)
env <- parent.frame()
shiny::observeEvent(tryCatch(
eval(eventExpr, env),
error = function(e) {
showNotification(paste("Error: ", e$message), type = "error")
}
),
{
tryCatch(
eval(handlerExpr, env),
error = function(e) {
showNotification(paste("Error: ", e$message), type = "error")
}
)
}, ...)
}
【问题讨论】:
标签: r error-handling shiny user-experience