Я полагаю, вам нужно будет создать «деструктор» для вашего модуля и убедиться, что клиент модуля («основное приложение») вызывает деструктор в нужное время. Например, предположим, что модуль возвращает деструктор как закрытие.
library(shiny)
## module definition
module_with_destructor <- function(input, output, session) {
output$plot <- renderPlot({
plot(1:input$n)
})
destructor <- function() {
# add more cleanup logic here
output$plot <- NULL
}
return(destructor)
}
Теперь нам нужно убедиться, что основное приложение выполняет деструктор, когда память должна быть освобождена.
## main app (client)
myenv <- new.env()
observeEvent(input$create_module, {
if (is.null(myenv$destructor))
myenv$destructor <- callModule(module_with_destructor, "module_id")
})
observeEvent(input$destroy_module, {
if (!is.null(myenv$destructor))
myenv$destructor()
})
Конечно, вам придется реализовать несколько дополнительных logi c, чтобы использовать эту идею с динамическим c количеством модулей. Однако в вашем случае вы можете просто создать список, который собирает все отдельные деструкторы, а затем перебирать их.