Search code examples
rcurlgethttr

How can I send a GET request without waiting for the response


I am trying to run a GET request inside a shinyApp, but I don't want to wait for the response as it would take quite a long time to process and I dont need really need the response inside the shinyApp, although a status code would be nice, but it is not obligatory.

Or is there maybe a function, that sends an async request? Like wrapping the whole GET inside a future/promise?

Currently I have this observeEvent in my shinyApp:

  observeEvent(input$import, {
    httr::GET(url = "https://someurl/that/takes/a/long/time")
  })

Is the curl_fetch_multi from the curl package suited for that task?


Solution

  • Here is a way to run GET asynchronously and in a intra-session non-blocking manner (observer returning nothing):

    library(shiny)
    library(future)
    library(promises)
    library(future.callr)
    library(httr)
    
    plan(callr)
    
    queryGoogle <- function(queryString) {
      myResponse <- httr::GET("http://google.com/", path = "search", query = list(q = queryString))
      return(myResponse)
    }
    
    ui <- fluidPage(
      br(),
      textOutput("time_output"),
      br(),
      textInput(inputId="query_input", label = NULL, value = "", placeholder = "Search google..."),
      actionButton("import", "Query"),
      hr(),
      textOutput("query_output")
    )
    
    server <- function(input, output, session) {
      futureData <- reactiveValues(response = NULL)
      
      observeEvent(input$import, {
        myFuture <- future({
          queryGoogle(isolate(input$query_input))
        })
        
        then(
          myFuture,
          onFulfilled = function(value) {
            futureData$response <- value
          },
          onRejected = NULL
        )
        return(NULL)
      })
      
      output$query_output <- renderPrint({
        req(futureData$response)
      })
      
      time <- reactive({
        invalidateLater(500, session)
        Sys.time()
      })
      
      output$time_output <- renderText({ paste("Something running in parallel:", time()) })
    }
    
    shinyApp(ui, server)
    

    This is a slight modification of my answer here.

    Please also read Joe Cheng's related answer here carefully.