你如何制作包含Shiny反应函数()的函数?

时间:2015-03-09 10:30:48

标签: r shiny

我正在开发一个包含大量“锅炉板”闪亮输入和输出对象的包,并将它们包装在一个函数中。我们的想法是为快速启动应用程序牺牲一些自定义。

例如:

功能来源或包

AuthMenuMacro <- function(input, session, code){

  …other observe functions that update menus….

  …other output functions that output plots, data tables….

  AuthToken <- reactive({

    token <- getTokenFromCode(code)

  })

}

server.r

code <- createAuthenticationCode()

shinyServer(function(input, output, session)){

  AuthMenuMacro(input, output, code)

  output$API_plot <- renderPlot({

    ## error as can’t see function AuthToken() within AuthMenuMacro()
    data <- getAPIData(AuthToken())

    plot(data)

  }) 
}

反应函数AuthToken()在另一个函数中,我无法从封闭函数外部达到它的值。我得到各种错误报告,我无法使用反应性环境等。

我尝试使用列表返回,但这给出了一个错误:

Error in .getReactiveEnvironment()$currentContext() : 
  Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

尝试通过列表返回

AuthMenuMacro <- function(input, session, code){

  …other observe functions that update menus….

  …other output functions that output plots, data tables….

  AuthToken <- reactive({

    token <- getTokenFromCode(code)

  })

  AuthTable <- reactive({

    table <- getTableFromCode(code)      

  })

  return(list(code=AuthToken(),
              table=AuthTable())

}

我也尝试过使用&lt;&lt; - 和环境,以及reactiveVariables(),但它似乎不起作用,但我的语法可能不对。

如果在上面的示例中我将AuthToken()和其他函数放在'auth.r'中并使用以下函数来源,我可以接近我想要的内容:

server.r

code <- createAuthenticationCode()

shinyServer(function(input, output, session)){

  source('auth.r', local=T)

  output$API_plot <- renderPlot({

    ## now works as AuthToken() in correct environment
    data <- getAPIData(AuthToken())

    plot(data)

  }) 
}

...但是如果可能的话,我希望通过函数来​​帮助简化和传递变量。

编辑:回答如下,但澄清:

我使用Shiny样式对象返回列表,而不仅仅将其视为普通的R函数。

e.g。 AccountCode()错误,AccountCode是对的。

AuthMenuMacro <- function(input, session, code){

  …other observe functions that update menus….

  …other output functions that output plots, data tables….

AuthToken <- reactive({

    token <- getTokenFromCode(code)

})

AuthTable <- reactive({

  table <- getTableFromCode(code)      

})

return(list(code=AuthToken,  ## not AuthToken() as you would in server.r
          table=AuthTable))  ## not AuthTable() as you would in server.r

}

server.r

auth <- AuthMenuMacro
token <- auth$code ## not auth$code()
table <- auth$table ## not auth$table()

1 个答案:

答案 0 :(得分:1)

你可以让第一台server.r工作,但我觉得调用一个函数并让它在调用者的环境中添加变量真的很糟糕。如果您只想在呼叫者的环境中使用一个被动表达式,那该怎么做:

AuthMenuMacro <- function(input, session, code){
  …other observe functions that update menus….
  …other output functions that output plots, data tables….
  reactive({
    token <- getTokenFromCode(code)
  })
}

server.r:

code <- createAuthenticationCode()

shinyServer(function(input, output, session)){
  AuthToken <- AuthMenuMacro(input, output, code)
  output$API_plot <- renderPlot({
    ## error as can’t see function AuthToken() within AuthMenuMacro()
    data <- getAPIData(AuthToken())
    plot(data)
  }) 
}

如果要返回多个反应式表达式,则让AuthMenuMacro返回一个命名列表,其值都是反应式表达式。 e.g:

code <- createAuthenticationCode()

shinyServer(function(input, output, session)){
  auth <- AuthMenuMacro(input, output, code)
  output$API_plot <- renderPlot({
    ## error as can’t see function AuthToken() within AuthMenuMacro()
    data <- getAPIData(auth$AuthToken())
    plot(data)
  })
  observe({
    cat("Auth info:", auth$AuthInfo(), "\n")
  })
}