会话如何在闪亮的服务器中工作?

Dav*_*Mas 11 r shiny shiny-server

我在理解会话如何在闪亮服务器中工作时遇到了一些麻烦.我假设当用户关闭浏览器时会话结束,但是,通过使用print(session$isClosed())服务器函数我FALSE在开始时得到响应(那么没关系)然后当我关闭浏览器时没有任何反应.谁能给我一些关于闪亮服务器会话的线索?我想存储特定于会话的图,让用户只下载他们的图.

Enz*_*nzo 20

好吧,从一个闪亮的会话对象开始是一个闪亮的特定('R6')数据结构,由公共和私有元素组成.它的目的是记录一个用户和闪亮之间的关系的一个实例(稍后将详细介绍).

>str(session)
Classes 'ShinySession', 'R6' <ShinySession>
  Public:
    @uploadEnd: function (jobId, inputId) 
    @uploadieFinish: function () 
    @uploadInit: function (fileInfos) 
    allowReconnect: function (value) 
    clientData: reactivevalues
    clone: function (deep = FALSE) 
    close: function () 
    closed: FALSE
    decrementBusyCount: function () 
    defineOutput: function (name, func, label) 
    dispatch: function (msg) 
    doBookmark: function () 
    downloads: Map, R6
    exportTestValues: function (..., quoted_ = FALSE, env_ = parent.frame()) 
    files: Map, R6
    fileUrl: function (name, file, contentType = "application/octet-stream") 
    flushOutput: function () 
    freezeValue: function (x, name) 
    getBookmarkExclude: function () 
    getTestEndpointUrl: function (inputs = TRUE, outputs = TRUE, exports = TRUE, format = "rds") 
    groups: NULL
    handleRequest: function (req) 
    incrementBusyCount: function () 
    initialize: function (websocket) 
    input: reactivevalues
    isClosed: function () 
    isEnded: function () 
    makeScope: function (namespace) 
    manageHiddenOutputs: function () 
    manageInputs: function (data) 
    ns: function (id) 
    onBookmark: function (fun) 
    onBookmarked: function (fun) 
    onEnded: function (endedCallback) 
    onFlush: function (flushCallback, once = TRUE) 
    onFlushed: function (flushedCallback, once = TRUE) 
    onInputReceived: function (callback) 
    onRestore: function (fun) 
    onRestored: function (fun) 
    onSessionEnded: function (sessionEndedCallback) 
    output: shinyoutput
    outputOptions: function (name, ...) 
    progressStack: environment
    reactlog: function (logEntry) 
    registerDataObj: function (name, data, filterFunc) 
    registerDownload: function (name, filename, contentType, func) 
    reload: function () 
    request: environment
    resetBrush: function (brushId) 
    restoreContext: RestoreContext, R6
    rootScope: function () 
    saveFileUrl: function (name, data, contentType, extra = list()) 
    sendBinaryMessage: function (type, message) 
    sendCustomMessage: function (type, message) 
    sendInputMessage: function (inputId, message) 
    sendInsertUI: function (selector, multiple, where, content) 
    sendModal: function (type, message) 
    sendNotification: function (type, message) 
    sendProgress: function (type, message) 
    sendRemoveUI: function (selector, multiple) 
    session: active binding
    setBookmarkExclude: function (names) 
    setShowcase: function (value) 
    showProgress: function (id) 
    singletons: 
    token: d44d583f13b3cd4ccce43f59fe410f61
    unhandledError: function (e) 
    updateQueryString: function (queryString) 
    user: NULL
    wsClosed: function () 
  Private:
    .clientData: ReactiveValues, R6
    .input: ReactiveValues, R6
    .outputOptions: list
    .outputs: list
    bookmarkCallbacks: environment
    bookmarkedCallbacks: environment
    bookmarkExclude: 
    busyCount: 2
    closedCallbacks: environment
    createBookmarkObservers: function () 
    enableTestEndpoint: function () 
    fileUploadContext: environment
    flushCallbacks: environment
    flushedCallbacks: environment
    getOutputOption: function (outputName, propertyName, defaultValue) 
    inputMessageQueue: list
    inputReceivedCallbacks: environment
    invalidatedOutputErrors: Map, R6
    invalidatedOutputValues: Map, R6
    outputValues: list
    progressKeys: character
    registerSessionEndCallbacks: function () 
    restoreCallbacks: environment
    restoredCallbacks: environment
    sendErrorResponse: function (requestMsg, error) 
    sendMessage: function (...) 
    sendResponse: function (requestMsg, value) 
    shouldSuspend: function (name) 
    showcase: FALSE
    storeOutputValues: function (values = NULL) 
    testEndpointUrl: session/d44d583f13b3cd4ccce43f59fe410f61/dataobj/shinyte ...
    testValueExprs: list
    websocket: WebSocket
    write: function (json) 
Run Code Online (Sandbox Code Playgroud)

探索会话对象的一个​​好方法是使用闪亮的gallery client-data-and-query-string中闪亮示例.它允许see包含在例如session$clientdata对象的任何其他元素中的内容.

一些额外的和误导性的微不足道的观点:

  • 会话什么时候开始?当用户连接闪亮的应用程序时
  • 会话什么时候结束?当用户与闪亮的应用程序断开连接时

作为一个例子,为了说明问题实际上是如何复杂,如果我刷新浏览器,我结束当前会话并创建一个新会话.

结束时session$isClosed(),这不是在会话结束时连接到特定操作的正确功能.这实际上是一个闪亮的回调函数的作用

onSessionEnded(fun, session = getDefaultReactiveDomain())
Run Code Online (Sandbox Code Playgroud)

一个最小的例子可能如下:

library(shiny)

ui =(
  fluidPage(
    titlePanel("This is an example")
  )
)

server = function(input, output, session){
  session$onSessionEnded({
    print("Stop!")
    stopApp   
  }) 
}

runApp(list(ui = ui, server = server))
Run Code Online (Sandbox Code Playgroud)

如果您尝试刷新(或使用浏览器()分解)将打印"停止"并将停止该应用程序.

2017年9月26日编辑:

一般来说,如果会话的连续性很重要(在任何情况下都适合session直接测试代码Shiny Server或者Shiny Server Pro),我认为最好小心谨慎.可能是最重要的用例Shiny Server Pro,任何断开连接may都会影响登录状态等.

我也知道shiny团队已在最近的版本中对这些领域进行了更改.例如,似乎虽然onSessionEnded仍然有效,但它可能不再是这个用例的最佳功能.

请参阅以下代码作为示例(来自shiny参考指南),使用onStop,可以在会话结束时以及应用程序停止时工作.

library(shiny)

cat("Doing application setup\n")
 onStop(function() {
   cat("Doing application cleanup\n")
 })

 shinyApp(
   ui = basicPage("onStop demo"),

   server = function(input, output, session) {
     onStop(function() cat("Session stopped\n"))
   }
 )
Run Code Online (Sandbox Code Playgroud)