R有光泽:隔离会话变量

时间:2015-09-19 21:02:35

标签: r shiny

我正在尝试隔离包含会话值session$sendCustomMessage的部分,以便在单击ActionButton时发送消息。用户上传文件,然后ActionButton变为可见。只有在单击按钮时,我们才应输入server.R的隔离部分。在此之后,完成一些计算,并将文件返回给用户。但是,我无法正确隔离,即使没有单击ActionButton也会返回文件。这是我的应用程序:

server.R:

library(shiny)


shinyServer(function(input, output, session) {


  observe({

    inFile <- input$upload

    if (is.null(inFile))
      return(NULL)

    # Send message indicating that the file is now uploaded
    session$sendCustomMessage("upload_ready", list(fileSize=0))

    # Read the .csv file 
    df = readLines(inFile$datapath)

    # Isolate this section from the reactive context.
    # But this is executing even if the Action Button is not
    # clicked
    isolate({

      # Make this isolated section dependent on the start_proc ActionButton
      input$start_proc

      output$data_file <- downloadHandler(
        filename = function() {
          paste('probabilities-', Sys.Date(), '.txt', sep='')
        }
        ,
        content = function(file1) {
          writeLines(df, con = file1)
        }
      )

      # I think this is the problem, the session changes even if the
      # action button is not clicked, and this is why the code is going
      # into this section.
      session$sendCustomMessage("download_ready", list(fileSize=0))

    })

  })

})

ui.R

library(shiny)
library(shinyBS)

shinyUI(fixedPage(
  singleton(tags$head(HTML(
    '
    <script type="text/javascript">
    $(document).ready(function() {

    // disable download at startup. data_file is the id of the downloadButton

    $("#data_file").attr("disabled", "true").attr("onclick", "return false;");

    // Disable start_prob at the beginning
    $("#start_proc").hide();


    // When uploaded file is ready, give the option to start process
    Shiny.addCustomMessageHandler("upload_ready", function(message) {
    $("#start_proc").show();
    });  

    // When the start_proc button is clicked, hide the button and disable
    // 

    $("#start_proc").click(function(){
    $("#start_proc").hide();
    $("#upload").prop("disabled", true);
    });

    // Show the option to download the file when the download is ready.
    // Also hide the button stat_proc and reactivate the option to upload
    // a file.
    Shiny.addCustomMessageHandler("download_ready", function(message) {
    $("#upload").prop("disabled", false);
    $("#data_file").removeAttr("disabled").removeAttr("onclick").html(
    "<i class=\\"fa fa-download\\"></i>Download Ready");
    });
    })
    </script>
    '
  ))),
   fileInput("upload", ""),
   bsButton("start_proc", h5("Compute Probability\n"), size = "extra-small", style = "primary"),
   downloadButton("data_file"),
   helpText("Download will be available once the processing is completed.")
))

1 个答案:

答案 0 :(得分:3)

您的问题与会话变量完全无关。实际触发计算的唯一事件是input$upload。如果上传为空,则代码会跟随以下行

if (is.null(inFile))
  return(NULL)

一切都按预期工作。如果文件已上传,则程序到达隔离块。使用isolate括起来的任何变量都不被视为依赖项,因此在部分代码完全没有效果之后,假设您在注释中做出的假设完全错误:

isolate({
   # Make this isolated section dependent on the start_proc ActionButton
   input$start_proc
   ...
})

即使您将input$start_proc放在isolate块之外,您的代码也无法正常工作,因为您根本没有检查是否已点击操作按钮。

使代码工作的一种方法是按如下方式分离上传和下载逻辑:

shinyServer(function(input, output, session) {
    raw <- reactive({
        inFile <- input$upload
        if (is.null(inFile)) return()
        # Read the .csv file 
        readLines(inFile$datapath)
    })

    observe({
        if (is.null(raw())) return() # If input empty return
        # Send message indicating that the file is now uploaded
        session$sendCustomMessage("upload_ready", list(fileSize=0))
    })

    df <- eventReactive(
        input$start_proc, # Button clicked 
        {raw()} # Send data to download handler
    )

    observe({
        if (is.null(df())) return() # In "preprocessed" data empty return

        output$data_file <- downloadHandler(
            filename = function() {
                paste('probabilities-', Sys.Date(), '.txt', sep='')
            },
            content = function(file1) {
                writeLines(df(), con = file1)
            }
        )
        # And send meassage
        session$sendCustomMessage("download_ready", list(fileSize=0))
    })
})