Watch if R is running from Shiny

[This article was first published on Colin Fay, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Today I discovered that the <html> tag of a Shiny App gets the shiny-busy class when computation is done in the R process. Which means that you can potentially watch with JavaScript if the R process is running.

It’s pretty subtle and you have to be watching the html source code of your app while it is running, so I guess few people other than me enjoy doing that.

A POC

Here’s a POC of an application that shows a spinner every time R is running (well, it checks every 50 milliseconds if R is running, and if it is, shows the loader).

library(shiny)

ui <- fluidPage(
  tags$script(
    'function checkifrunning() {
      var is_running = $("html").attr("class").includes("shiny-busy");
      if (is_running){
        $("#loading").show()
      } else {
        $("#loading").hide()
      }
    }; 
    setInterval(checkifrunning, 50)'
  ), 
  tags$style(
    " body { text-align:center; }

    #loading {
      display: inline-block;
      border: 3px solid #f3f3f3; 
      border-top: 3px solid #3498db; 
      border-radius: 50%;
      width: 50px;
      height: 50px;
      animation: spin 1s ease-in-out infinite;
    }

    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }"
  ),
  
  column(12, actionButton("go1", "Simulate long process 1")),
  column(12, actionButton("go2", "Simulate long process 2")),
  column(12, actionButton("go3", "Simulate long process 3")),
  HTML(" "),
  column(12, tags$div(id = "loading",
    tags$script('$("#loading").hide()')))
  
)

server <- function(input, output, session) {
  observeEvent(input$go1, {
    for (i in 1:15) {
      print(i)
      Sys.sleep(0.1)
    }
  })
  observeEvent(input$go2, {
    for (i in 1:15) {
      print(i)
      Sys.sleep(0.1)
    }
  })
  observeEvent(input$go3, {
    for (i in 1:5) {
      print(i)
      Sys.sleep(0.1)
    }
  })
}

shinyApp(ui, server)

Result:

Why do that? Well, don’t. Here we just have a loader that pops up every time R is running, which is kind of brutal (and I’m not 100 % certain we can rely on this class change). Also, in my example, the JS code is run every 50 milliseconds… which is even more brutal. But in case it can be useful (or inspiring) to someone, I just wanted to share :).

And of course, with more hacking, this can ne combined with other JS & R code to make a smarter spinner.

About the code :

function checkifrunning() {
  var is_running = $("html").attr("class").includes("shiny-busy");
  if (is_running){
    $("#loading").show()
  } else {
    $("#loading").hide()
  }
}; 
setInterval(checkifrunning, 50);

I’m creating a function called checkifrunning(), that checks if the class of the html tag contains shiny-busy, and show() and hide() the loading div if ever it is.

With setInterval(checkifrunning, 50), I’m setting this function to be run every 50 milliseconds.

The loading CSS and div is inspired by the W3 tuto, with a little bit of tweaking.

To leave a comment for the author, please follow the link and comment on their blog: Colin Fay.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)