在我的Shiny页面上,有一个步骤读取一个大的日志文件,需要25秒才能加载。我想在用户点击按钮后显示进度条。否则他们可能会认为在他们等待时它不起作用。
#ui.R
#I have an actionButton to activate reading the log file
actionButton("getLog","Get Log data")
#server.R
observeEvent(input$getLog, {
nL = as.numeric(countLines("/script/cronlog.log"))
Log = read.table("/script/cronlog.log",sep = ";",skip = nL-1000)
LogFile = tail(Log,100)
colnames(LogFile) = "cronlog"
})
我试图使用withProgress,但我不知道如何用它来包装代码。我试过这样的事情:
observeEvent(input$getLog, {
withProgress(message = 'Calculation in progress',
detail = 'This may take a while...', value = 0, {
for (i in 1:60) {
incProgress(1/60)
Sys.sleep(0.25)
}
})
nL = as.numeric(countLines("/script/cronlog.log"))
Log = read.table("/script/cronlog.log",sep = ";",skip = nL-1000)
LogFile = tail(Log,100)
colnames(LogFile) = "cronlog"
})
进度条确实显示但似乎加载进度在进度条之后运行,这使得进程更长。我想我没有正确包装代码。
有什么建议吗?
提前谢谢!
答案 0 :(得分:2)
如果您申请的操作不是离散的,withProgress
对您没有多大帮助。您可以在各个语句之间增加进度条:
nL = as.numeric(countLines("/script/cronlog.log"))
incProgress(1/4)
log = read.table("/script/cronlog.log",sep = ";",skip = nL-1000)
incProgress(1/4)
...
但我怀疑它会产生巨大的影响。另一种方法是将输入文件分成多个块,并在每个文件之后单独读取这些增量计数器。
在实践中,我会考虑删除以下部分:
nL = as.numeric(countLines("/script/cronlog.log"))
并使用标准系统实用程序来管道所需的数据:
read.table(pipe("tail -n 1000 /script/cronlog.log"), sep = ";")
或直接与data.table::fread
:
fread("tail -n 1000 /script/cronlog.log", sep = ";")