I work on a Shiny application with shinydashboard
and somewhere in the app I want to show a notification telling the user how many other users are connected to the application at the same time.
I came up with a first piece of code that seems to work:
library(shiny)
ui=fluidPage(uiOutput("text"))
number.users <- 0 # global variable
server= function(input, output, session){
already.counted = FALSE
autoInvalidate = reactiveTimer(2000)
observe({
if (!already.counted) {
already.counted <- TRUE
number.users <<- number.users + 1
}
})
output$text = renderUI({
autoInvalidate()
h1(paste0("There are ", number.users, " user(s) connected to this app"))
})
onSessionEnded(function(){number.users <<- number.users - 1})
}
However it's not very "clean" and I'm afraid that my call to observe
and the invalidate every 2 secs are adding some useless computing time to my (already heavy) app. I was wondering if there was some kind of function in shiny
that triggers an event at the start of each new session, something like onsessionstart() that I could use directly to increment the global variable number.users
, and a way to notify other sessions that a new session has been opened? Or is there any simpler way to go?
Thanks
There are many reasons why a shiny app runs slower than expected. The most common reason is the Shiny app code has not been optimized. You can use the profvis package to help you understand how R spends its time. You also might want to make sure your server is large enough to host your apps.
To send your files to another user, email the files (perhaps in a zip file) or host the files online. Your user can place the files into an app directory in their working directory. They can launch the app in R with the same commands you used on your computer.
Shiny Server Pro allows you to scale Shiny applications to support multiple simultaneous users. The scaling is accomplished by setting 3 arguments in the configuration file ( /etc/shiny-server/shiny-server.
Secure. shinyapps.io is secure-by-design. Each Shiny application runs in its own protected environment and access is always SSL encrypted. Standard and Professional plans offer user authentication, preventing anonymous visitors from being able to access your applications.
The root server function is called once for every new session, and effectively serves as the "onSessionStart" callback. I think what you're doing is fine, except the observe
isn't really necessary.
To share global state between sessions in a more reactive manner, you can initialize a reactiveVal
or reactiveValues
object in global scope (outside of a reactive context), and then take a reactive dependency on it within each session. Any updates to these reactive values will immediately propagate to all other sessions.
library(shiny)
users = reactiveValues(count = 0)
ui = fluidPage(uiOutput("text"))
server = function(input, output, session) {
onSessionStart = isolate({
users$count = users$count + 1
})
onSessionEnded(function() {
isolate({
users$count = users$count - 1
})
})
output$text = renderUI({
h1(paste0("There are ", users$count, " user(s) connected to this app"))
})
}
shinyApp(ui, server)
Btw, a more complex example of inter-session communication, though maybe a bit old now, is the Shiny chat room app - http://shiny.rstudio.com/gallery/chat-room.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With