首页 > 解决方案 > 使用 Javascript 输出更新 Shiny UI 布局

问题描述

我有一个在云上运行的闪亮应用程序运行时间很长(大量计算大约需要 25 分钟)导致超时。但是,如果我在应用程序运行时继续与页面交互(例如导航导航栏或移动滑块..),则不会发生超时。一个可能的解决方案是通过每 5 秒左右更新当前页面上的值来保持 web-socket 处于活动状态。我在这里借用了这个想法https://community.rstudio.com/t/keep-shiny-app-running-in-shiny-server-no-greying-out/27784/4

ui <- fluidPage(
  "Am I losing connection?",
  tags$div(style = "position: absolute; top: -100px;",
    textOutput("clock")
  )
)
server <- function(input, output) {
  output$clock <- renderText({
    invalidateLater(5000)
    Sys.time()
  })
}
shinyApp(ui = ui, server = server)

但是,这也会失败,因为在应用程序在后台运行时,UI 值似乎不会更新或刷新,直到它完成当前任务。因此,在 server.R 块中执行此操作似乎不是解决方案。

后来我尝试通过包含可以在应用程序在后台运行时更新或刷新 UI 的 JS 代码来做不同的事情。我想出的是这个...

function time_function(){
var today1 = new Date();
var hr = today1.getHours();
var mn = today1.getMinutes();
var ss = today1.getSeconds();

if (hr.toString().length <2 ){hr = '0' + hr;} 
if (mn.toString().length <2 ){mn = '0' + mn;}
if (ss.toString().length <2 ){ss = '0' + ss;}

console.log(hr + ':' + mn + ':' + ss);

}

setInterval(time_function,5000)

... 鉴于我可以textOutput("time_display") 每 5 秒更新一次闪亮的 UI 以保持页面处于活动状态并防止与 websocket 的连接丢失。这正是我卡住的地方,因为我无法textOutput("time_display")使用 JS 函数的刷新值进行更新time_function()

我感谢提供的所有帮助。谢谢!

标签: javascriptrshiny

解决方案


我设法找到了一种解决方法,即使在 server.R 中运行密集型工作负载时也可以保持 R/Shiny 网页处于活动状态。我想分享我的工作解决方案。

第一步是在Shiny 的 UI、fluidPage() 部分中创建一个div标签或对象。我有一个分配给它的“time_stamp”id。

ui<-fluidPage(
  
titlePanel(" Testing 5 sec display of clock"),

HTML('<div id="time_stamp"></div>'), // comment: new object created. We write to it using js code.

br(),

tags$script(src = "time_print.js")
)
//server.R

server = function(input,output,session){

// do some complex tasks..

}

tags$script位是读取 .js 文件的位置。为此,我将 time_print.js 文件保存www我们的 shinyApp.R 文件同名的目录中。.js 文件中的代码如下所示:

function js_print_time(){

var today1 = new Date();
var hr = today1.getHours();
var mn = today1.getMinutes();
var ss = today1.getSeconds();

if (hr.toString().length <2 ){hr = '0' + hr;} 
if (mn.toString().length <2 ){mn = '0' + mn;}
if (ss.toString().length <2 ){ss = '0' + ss;}

var pstamp = hr + ':' + mn + ':' + ss;  

document.getElementById("time_stamp").textContent = "";       //clear current div object contents.

document.getElementById("time_stamp").textContent += pstamp;  // Append pstamp to current value of div object, "". I thank Jesus!

}


setInterval(one_time_print,5000);

它的作用是每 5000 毫秒(5 秒)将 javascript 函数的输出打印js_print_time() 到闪亮的网页(在“time_stamp”div 上),无论闪亮应用的 server.R 中是否正在运行繁重的任务。


推荐阅读