单个正在运行的R Shiny应用程序的多个会话之间的交互

时间:2016-12-24 20:32:44

标签: r interactive shiny shiny-reactivity

我想构建一个R Shiny应用程序,它能够将信息从一个正在运行的实例传递到其他可能正在运行的实例。到目前为止,我没有找到任何可以帮助我的东西,而且我希望能够正确地做到这一点,而不是诉诸于全局变量和/或写入文件等(我在下面的例子中使用了全局变量,我知道这是一个不好的做法;我怀疑写文件也不是一个好习惯。

例如,假设我在服务器上运行了我的App.R并且 Tim Jack John 让它打开。如何 Tim 看到下面的内容,当 Jack John 同时使用该应用程序并按下按钮时,如下例所示?

App.R:

library(shiny)

# Somehow interactively visible variable? (I know global variables are bad, I wouldn't want to use such)
txt <<- ""

shinyApp(
    ui = fluidPage(
        textInput("name", "User name", value="USERNAME"),
        actionButton("button", "Button"),
        htmlOutput("text")
    ),
    server = function(input, output, session){
        a <- eventReactive(input$button, {
            txt <<- paste(txt, "Button pressed by", input$name, "at", Sys.time(), "<br>")
            txt

        })
        output$text <- reactive({
            HTML(a())
        })
    }
)

来自各个用户的多个按钮按下后的示例所需输出,这些用户都在其浏览器中运行了应用程序实例(所有用户都选择了唯一的输入$ name,但显然唯一的会话ID会更好):

Example user case

非常感谢任何见解,谢谢!

1 个答案:

答案 0 :(得分:4)

我已经在一个闪亮的服务器实例上测试了你的代码,它按预期工作:即我得到的打印输出类似于你要求的打印输出。

我有点困惑:你到底在寻找什么?

无论如何,作为一般性评论,我不同意使用<<-是错误的,或者global variables(通常或在闪亮的应用中)是

他们有自己的位置,而且一个典型的用例是跨会话/用户传递状态。

另一种方法是使用shiny reactiveValues,如下所示:

 values <- reactiveValues()
 values$lognames <- ''
 ...
 ui <- (...)

 server <- function(input, output, session){

 a <- eventReactive(input$button, {
 values$lognames <- paste(values$lognames, "Button pressed by", input$name, "at", Sys.time(), "<br>")
 values$lognames
 })
...
 }

但作为一般注意事项,这种类型的设计虽然可能,但最终可能会给应用程序带来有状态,很快就会增加其复杂性,并且会违背{{1范式。

我强烈建议在这条道路上的每一步之前要仔细考虑。我有过实施闪亮应用程序的经验,这些应用程序随着这些reactive的激增而迅速升级。我必须跟踪所有状态的变化,导致脆弱,难以调试的应用程序。