How to exit a Shiny app and return a value
There is a stopApp
function that stops the running app and returns an optional value:
myValue <- runApp(list(
ui = bootstrapPage(
numericInput('n', 'Number of obs', 100),
actionButton("myBtn", "Press ME!"),
plotOutput('plot')
),
server = function(input, output, session) {
output$plot <- renderPlot({ hist(runif(input$n)) });
observe({
if(input$myBtn > 0){
stopApp(7)
}
})
}
))
On stopping:
> myValue
[1] 7
How does one terminate all processes upon Shiny app end?
@PorkChop's comment is pointing in the right direction. However, I'd recommend using processx::process
rather than run
as it provides us with methods to control the started process from within R. See ?process
. (run
by the way is also based on the process class.)
The main problem here is, that running the process synchronously (wait=TRUE
) blocks the R session. Accordingly onStop
won't fire until R is back in control.
Therefore you can't trigger anything once the browser window was closed because the shiny-session continues to run until the external program is finished and R can close the shiny-session.
On session end, the below code checks if the asynchronously started process is still alive and kills it if necessary (tested on windows only).
library(shiny)
library(processx)
ui <- fluidPage(
actionButton("runBtn", label="Run a program that consumes many resources"),
actionButton("stopSession", "Stop session")
)
server <- function(input, output, session) {
myProcess <- NULL
observeEvent(input$stopSession, {
cat(sprintf("Closing session %s\n", session$token))
session$close()
})
observeEvent(input$runBtn,
{
if(Sys.info()[["sysname"]]=="Windows"){
writeLines(text = c("ping 127.0.0.1 -n 60 > nul"), con = "sleep.bat")
myProcess <<- process$new("cmd.exe", c("/c", "call", "sleep.bat"), supervise = TRUE, stdout = "")
} else {
myProcess <<- process$new("sleep", "60", supervise = TRUE, stdout = "")
}
# myProcess$wait() # wait for the process to finish
})
onStop(function(){
cat(sprintf("Session %s was closed\n", session$token))
if(!is.null(myProcess)){
if(myProcess$is_alive()){
myProcess$kill()
}
}
})
}
shinyApp(ui, server)
Regarding the different session callback functions see this related post.
As requested here the process is wrapped in a reactiveVal
:
library(shiny)
library(processx)
ui <- fluidPage(
actionButton("runBtn", label="Run a program that consumes many resources"),
actionButton("stopSession", "Stop session")
)
server <- function(input, output, session) {
myProcess <- reactiveVal(NULL)
observeEvent(input$stopSession, {
cat(sprintf("Closing session %s\n", session$token))
session$close()
})
observeEvent(input$runBtn,
{
if(Sys.info()[["sysname"]]=="Windows"){
writeLines(text = c("ping 127.0.0.1 -n 60 > nul"), con = "sleep.bat")
myProcess(process$new("cmd.exe", c("/c", "call", "sleep.bat"), supervise = TRUE, stdout = ""))
} else {
myProcess(process$new("sleep", "60", supervise = TRUE, stdout = ""))
}
# myProcess()$wait() # wait for the process to finish
})
onStop(function(){
cat(sprintf("Session %s was closed\n", session$token))
if(!is.null(isolate(myProcess()))){
if(isolate(myProcess()$is_alive())){
isolate(myProcess()$kill())
}
}
})
}
shinyApp(ui, server)
How to return value from R Shiny Session
After running and closing the app:
customcolors <- scan("colorfile.txt", character())
customcolors
# [1] "#a96337" "#f0ecb0" "#4a4000" "#001a24"
Or run the app with:
customcolors <- runApp(CherryPickPalette("BiryaniRice","Kulfi","Haveli2"))
How to stop resetting a variable in R-Shiny?
You can define it as a reactive value:
server <- shinyServer(function(input, output, session) {
level_init <- reactiveValues(level="Value1")
level_react <- reactive({
level_init$level <- "Value2"
})
print(isolate(level_init$level))
observeEvent(input$Reset,{
output$graph <- renderPlot({ plot(1, 1) }) }, ignoreNULL = F)
# interaction click in graph
observe({
if(is.null(input$plot_click$x)) return(NULL)
x <- sample(20:30,1,F)
level_react()
print(level_init$level)
isolate({
output$graph <- renderPlot({
draw.single.venn(x)
})
})
})
})
shinyApp(ui=ui,server=server)
Disconnect from PostgreSQL when close R Shiny App
Do you know about the onSessionEnded
of the session
variable?
Here's a very basic example that sets a random session id to each user and when they close the window, a function runs that says what session id was closed. It's just a proof of concept, you can tailor it to your database needs trivially I hope
runApp(shinyApp(
ui = fluidPage(
textOutput("sessionId")
),
server = function(input, output, session) {
sessionId <- as.integer(runif(1, 1, 100000))
output$sessionId <- renderText(paste0("Session id: ", sessionId))
session$onSessionEnded(function() {
cat(paste0("Ended: ", sessionId))
})
}
))
Edit:
Op said he needs the variable to be reactive, so here's a modification that I believe would allow him what he wants
runApp(shinyApp(
ui = fluidPage(
textOutput("sessionId")
),
server = function(input, output, session) {
values <- reactiveValues(sessionId = NULL)
values$sessionId <- as.integer(runif(1, 1, 100000))
output$sessionId <- renderText(paste0("Session id: ", values$sessionId))
session$onSessionEnded(function() {
observe(cat(paste0("Ended: ", values$sessionId)))
})
}
))
Disclaimer: I'm not sure if putting the observe inside the onSessionEnded callback is the best approach. This works, but I can't vouch for it's "correctness".
How to stop end shiny session by closing the browser
If you want to plot your histogram while the session is active, take the second option. As mentioned by @Waldi the first option plots your histogram when the session is ended, and the user will thus never see the histogram. See here an example of the two options:
First option: we never see the table
rm(list=ls())
library(shiny)
doshiny <- function() {
app=shinyApp(
ui = fluidPage(
textInput("textfield", "Insert some text", value = "SomeText"),
dataTableOutput('table')
),
server = function(input, output, session) {
session$onSessionEnded(function() {
output$table <- renderDataTable(iris)
stopApp()
})
}
)
runApp(app)
}
openshiny <- function() {
doshiny()
print("Finished.")
}
openshiny()
Second option: we see the table
rm(list=ls())
library(shiny)
doshiny <- function() {
app=shinyApp(
ui = fluidPage(
textInput("textfield", "Insert some text", value = "SomeText"),
dataTableOutput('table')
),
server = function(input, output, session) {
output$table <- renderDataTable(iris)
session$onSessionEnded(function() {
stopApp()
})
}
)
runApp(app)
}
openshiny <- function() {
doshiny()
print("Finished.")
}
openshiny()
Related Topics
Differencebetween Names and Colnames
Figure Captions, References Using Knitr and Markdown to HTML
How to Get Geom_Vline to Honor Facet_Wrap
Colorize Parts of the Title in a Plot
Create a Gif from a Series of Leaflet Maps in R
How to Write an R Function That Evaluates an Expression Within a Data-Frame
How to Create Thiessen Polygons from Points Using R Packages
How to Use the Row.Names Attribute to Order the Rows of My Dataframe in R
How Make 2 Column Layout in R Markdown When Rendering PDF
Include Data Examples in Developing R Packages
In R, Extract Part of Object from List
How to Create 3D - Matlab Style - Surface Plots in R
Ggplot: Multiple Years on Same Plot by Month
R: Generate All Permutations of Vector Without Duplicated Elements
Scale/Normalize Columns by Group
Remove Strings Found in Vector 1, from Vector 2
Explanation of R: Options(Expressions=) to Non-Computer Scientists