Creating a reactiveFileReader directly within renderText

Are the two chunks of code

logTimer <- reactiveFileReader(intervalMillis = 500, session=NULL, 
                         filePath = logFile, readFunc = readLines)

output$logf <- renderPrint({
    logTimer()
})

and

 output$logf <- renderPrint({
      reactiveFileReader(intervalMillis = 500,  session=NULL,
                  filePath = logFile, readFunc = readLines)() 
    })

Equivalent in shiny ?

they are not perfectly equivalent if only for the reason that one creates an object named logTimer and the other doesnt.

Of course, but I wonder if creating the reactiveFileReader directly inside renderPrint is erroneous. Here is a (somewhat lengthy) chunk of code where it does not work whereas using a reactive variable does.

library(shiny)

library(processx)

asyncUI <- function(id) {
  ns <- NS(id)
  tagList(
    fluidRow(
      actionButton(ns("runProc"), "Sleep"),
      verbatimTextOutput(ns("logf")),
    ),
  )
}

asyncServer <- function(id, logFile)
  moduleServer(id, function(input, output, session) {

        mainProcess <<- NULL
    
    observeEvent(input$runProc, {
      mainProcess <<- process$new("count.tcsh")
    })
    procTimer <- reactivePoll(1000,  NULL, 
                              checkFunc = function() {
                                if(is.null(mainProcess))
                                  NULL
                                else 
                                  mainProcess$is_alive()
                                
                              },
                              valueFunc = function() { 
                                if(is.null(mainProcess))
                                  NULL
                                else
                                  mainProcess$is_alive()
                              })
#    logTimer <- reactiveFileReader(intervalMillis = 500, session=NULL, filePath = logFile, readFunc = readLines)
    output$logf <- renderPrint({
      req(!is.null(procTimer()))
      reactiveFileReader(intervalMillis = 500, session=NULL, filePath = logFile, readFunc = readLines)() 
      #logTimer()
    })
    
     
      
    
  })

ui <- fluidPage(
 
  asyncUI("myrun"),
  
)

server <- function(input, output, session) {
  asyncServer("myrun", logFile="count.log")
}

shinyApp(ui, server)

This runs a script count.tcsh that writes to a file counts.log. It displays the log in real time. count.tcsh script is

#!/bin/tcsh
echo "Begin script" >! count.log
foreach i (`seq 1 10`)
 sleep 1
 echo $i  seconds passed >> count.log
end

echo Finished script >> count.log

When I run it (in Linux), the version above does not display all the log file counts from 1 to 10, but (for a reason unknown to me) stops at count 2-3. If I use a variable inside renderPrint, it works just fine.

Myself I would prefer to be practical and write the cleanest easiest to follow code that I know how to do.
Though I do completely get the desire to understand the framework, and I have to admit I don't have the chops to do that for you ...

Of the different options I show below. 1 and 3 makes sense to me, and I have used them often in the past, and 2 seems to follow your imagined pattern, but I wouldn't have thought to use it.. maybe a lack of imagination on my part.. , and I don't have a clear reason for you as to why it doesn't work, you may need someone with knowledge of shiny internals to figure it for you, I expect there's something about it that does not reliably build the reactive graph.

Anyways, you have a solution so its not a big defeat, simply revert to using your logTimer object.

Example of problematic pattern:


library(shiny)

ui <- fluidPage(
  actionButton("mybtn","press"),
  verbatimTextOutput("mytext1"),
  verbatimTextOutput("mytext2"),
  verbatimTextOutput("mytext3")
)

server <- function(input, output, session) {
  
  some_named_reactive <- reactive({input$mybtn})
  
  output$mytext1 <- renderPrint({
    some_named_reactive()
  })
  
  output$mytext2 <- renderPrint({
    # best avoided
    reactive({input$mybtn})()
  })

  output$mytext3 <- renderPrint({
    input$mybtn
  })
}

shinyApp(ui, server)
1 Like

Thank you for the thinking.

By the way, your reprex is much clearer than my long example.

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.