Должна быть возможность использовать пакеты R future
и promises
для запуска асинхронной (длительной) обработки через приложения Shiny без остановки остальной части приложения, пока асинхронный процесс выполняется в другом процессе R.
См .:
https://cran.r-project.org/web/packages/promises/vignettes/intro.html
https://cran.r-project.org/web/packages/promises/vignettes/overview.html
https://cran.r-project.org/web/packages/promises/vignettes/futures.html
https://cran.r-project.org/web/packages/promises/vignettes/shiny.html
Я заставил это работать в среде на основе R-скриптов, но не могу заставить это работать, когда я реализую простое блестящее приложение с 2 функциями. Функция «not-async» всегда блокируется во время работы асинхронной функции, но это не должно иметь место.
Я разместил тот же вопрос в репозитории GitHub пакета promises
: https://github.com/rstudio/promises/issues/23
Я также публикую это здесь, надеясь, что кто-то может помочь.
Вопрос:
- Можете ли вы взглянуть на блестящий пример приложения, размещенный ниже, и сообщить мне, почему асинхронная обработка блокирует приложение? (Не должно блокировать).
- В идеале, можете ли вы предоставить небольшой пример приложения с неблокирующей асинхронностью и нормальной функциональностью (доступной во время выполнения асинхронизации)?
Окружающая среда
Mac OS 10.12
$ R --version
R version 3.4.3 (2017-11-30) -- "Kite-Eating Tree"
remove.packages("future")
remove.packages("promises")
remove.packages("shiny")
install.packages("future")
install.packages("devtools")
devtools::install_github("rstudio/promises")
devtools::install_github("rstudio/shiny")
> packageVersion("future")
[1] ‘1.8.1’
> packageVersion("promises")
[1] ‘1.0.1’
> packageVersion("shiny")
[1] ‘1.0.5.9000’
Односторонний вопрос о версии блестящего пакета, https://rstudio.github.io/promises/articles/intro.html говорит, что это должно быть> = 1.1, но даже при установке с помощью devtools версия остается 1.0.5 .... Это проблема или в документе есть опечатка?
Во-первых, вы можете использовать обещания с блестящими выходами. Если вы используете асинхронно-совместимую версию Shiny (версия> = 1.1), все встроенные функции renderXXX могут работать как с обычными значениями, так и с обещаниями.
Пример выпуска
Я реализовал это простое блестящее приложение, вдохновленное примером по URL-адресам, упомянутым выше.
У блестящего приложения есть 2 "секции":
- Кнопка для запуска «длительной» асинхронной обработки. Это моделируется функцией
read_csv_async
, которая спит несколько секунд, считывает CSV-файл в кадр данных. Затем df отображается под кнопкой.
- Простая функциональность, которая должна работать в любое время (в том числе, когда была запущена асинхронная обработка): она включает ползунок, определяющий количество случайных значений, которые должны быть сгенерированы. Затем мы отображаем гистограмму этих значений.
Проблема в том, что вторая функция (обновление графика гистограммы) блокируется во время асинхронной обработки.
* * Global.R тысяча сорок-девять
library("shiny")
library("promises")
library("dplyr")
library("future")
# path containing all files, including ui.R and server.R
setwd("/path/to/my/shiny/app/dir")
plan(multiprocess)
# A function to simulate a long running process
read_csv_async = function(sleep, path){
log_path = "./mylog.log"
pid = Sys.getpid()
write(x = paste(format(Sys.time(), "%Y-%m-%d %H:%M:%OS"), "pid:", pid, "Async process started"), file = log_path, append = TRUE)
Sys.sleep(sleep)
df = read.csv(path)
write(x = paste(format(Sys.time(), "%Y-%m-%d %H:%M:%OS"), "pid:", pid, "Async process work completed\n"), file = log_path, append = TRUE)
df
}
ui.R
fluidPage(
actionButton(inputId = "submit_and_retrieve", label = "Submit short async analysis"),
br(),
br(),
tableOutput("user_content"),
br(),
br(),
br(),
hr(),
sliderInput(inputId = "hist_slider_val",
label = "Histogram slider",
value = 25,
min = 1,
max = 100),
plotOutput("userHist")
)
server.R
function(input, output){
# When button is clicked
# load csv asynchronously and render table
data_promise = eventReactive(input$submit_and_retrieve, {
future({ read_csv_async(10, "./data.csv") })
})
output$user_content <- renderTable({
data_promise() %...>% head(5)
})
# Render a new histogram
# every time the slider is moved
output$userHist = renderPlot({
hist(rnorm(input$hist_slider_val))
})
}
data.csv
Column1,Column2
foo,2
bar,5
baz,0
Спасибо!