You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用rdrop2存储数据至Dropbox时,YouTube-API关联RadioButton失效?

问题排查与解决方案

核心问题定位

添加rdrop2存储逻辑后,视频结束后单选按钮不显示,大概率是rdrop2的同步操作阻塞了Shiny的事件循环,导致shinyjs的UI更新指令被延迟或跳过;也可能是存储操作的上下文干扰了session状态,使得shinyjs无法正常调用。

针对性解决方法

方法1:调整执行顺序+异步存储

优先处理UI更新,再将rdrop2操作放到后台异步执行,避免阻塞UI响应:

library(shiny)
library(shinyjs)
library(rdrop2)
library(future)
library(promises)

# 配置异步运行环境
plan(multisession)

ui <- fluidPage(
  useShinyjs(),
  uiOutput("random_video"),
  # 初始隐藏单选按钮
  hidden(radioButtons("next_page_radio", "确认进入下一页?", choices = c("确认" = "next")))
)

server <- function(input, output, session) {
  # 随机渲染视频并绑定结束事件
  output$random_video <- renderUI({
    video_list <- c("video1.mp4", "video2.mp4", "video3.mp4")
    selected_video <- sample(video_list, 1)
    tags$video(
      src = selected_video,
      type = "video/mp4",
      controls = TRUE,
      # 视频结束时触发输入更新,高优先级确保及时传递
      onended = "Shiny.setInputValue('video_done', true, {priority: 'event'})"
    )
  })

  # 监听视频结束事件
  observeEvent(input$video_done, {
    # 第一步:立即显示单选按钮
    shinyjs::show("next_page_radio")
    
    # 第二步:异步执行rdrop2存储,不阻塞UI
    future({
      # 替换为你的调研数据存储逻辑
      # 示例:drop_write(data.frame(response = input$xxx), "survey_data.csv", overwrite = TRUE)
    }) %>% then(function(res) {
      # 存储完成后的可选回调(如打印日志)
      message("数据已同步到Dropbox")
    }) %>% catch(function(err) {
      message("存储失败:", err)
    })
  })

  # 下一页跳转逻辑
  observeEvent(input$next_page_radio, {
    # 替换为你的多页切换逻辑(如updateTabsetPanel、shiny.router跳转等)
    message("进入下一页")
  })
}

shinyApp(ui, server)

方法2:用renderUI替代shinyjs显隐

彻底绕开shinyjs的调用,通过响应式值动态生成单选按钮:

library(shiny)
library(rdrop2)
library(future)
library(promises)

plan(multisession)

ui <- fluidPage(
  uiOutput("random_video"),
  uiOutput("next_page_radio")
)

server <- function(input, output, session) {
  # 响应式值标记视频是否结束
  video_ended <- reactiveVal(FALSE)

  # 随机渲染视频
  output$random_video <- renderUI({
    video_list <- c("video1.mp4", "video2.mp4", "video3.mp4")
    selected_video <- sample(video_list, 1)
    tags$video(
      src = selected_video,
      type = "video/mp4",
      controls = TRUE,
      onended = "Shiny.setInputValue('video_done', true, {priority: 'event'})"
    )
  })

  # 监听视频结束事件,更新状态并异步存储
  observeEvent(input$video_done, {
    video_ended(TRUE)
    future({
      # 替换为你的rdrop2存储逻辑
    })
  })

  # 根据视频结束状态动态生成单选按钮
  output$next_page_radio <- renderUI({
    if (video_ended()) {
      radioButtons(
        "next_page",
        "确认进入下一页?",
        choices = c("是" = "yes")
      )
    } else {
      NULL
    }
  })

  # 下一页跳转逻辑
  observeEvent(input$next_page, {
    # 替换为你的多页切换逻辑
  })
}

shinyApp(ui, server)

关键注意点

  1. 所有rdrop2的IO操作必须异步执行(用future/promises包),避免阻塞Shiny的事件循环;
  2. 视频结束的JS事件要设置priority: 'event',确保输入值能立即传递到R端;
  3. 如果使用shinyjs,确保useShinyjs()在UI中正确加载,且没有被其他代码覆盖session上下文。

内容的提问来源于stack exchange,提问作者dot_codes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 22:26:32