Соревнование между наблюдаемым событием и обновлением * Ввод при быстром нажатии кнопки действия - PullRequest
3 голосов
/ 08 мая 2020

Фон

У меня есть блестящее приложение для оценки студенческих работ. Работа учащегося отображается на экране, а оценщик использует различные кнопки / галочки для выставления оценок. Затем есть кнопка «Далее» для перехода к go следующему учащемуся (с сохранением оценок и т. Д. c). Также есть кнопка «Назад», позволяющая оценщикам просматривать историю оценок, поэтому при каждом нажатии кнопки «Далее» или «Назад» существующая оценка за работу учащегося загружается в кнопки / галочки.

Проблема

К сожалению, существует состояние гонки между обновлением пользовательского интерфейса и переходом к следующему или предыдущему учащемуся: ObserverEvent () для Next, например, сначала проверяет + обновляет оценку текущего учащегося (определяется состоянием кнопок / флажков, или, альтернативно, реактивное значение), а затем загружает текущие оценки нового учащегося и обновляет пользовательский интерфейс. Быстрое нажатие кнопки «Далее» означает, что сообщения для обновления пользовательского интерфейса могут быть отложены, и, таким образом, состояние пользовательского интерфейса (или любые реакции, в которых сохраняются оценки) обновляются на основе старой информации от других учащихся. Затем это сравнивается с текущими оценками ученика и перезаписывается - не очень хорошая ситуация. Пока грейдеры go достаточно медленно нажимают кнопку «Далее», все, конечно же, работает нормально - неисправны только более быстрые кликеры. Флажок заполняется из stored_checks, когда вы нажимаете кнопку «Далее». Если вы нажмете «Далее» достаточно быстро, вы получите сообщение «проверка изменена» на консоль, даже если статус этой записи, очевидно, не изменился, так как кнопка галочки не была нажата.

Причина в том, что updateCheckboxInput приводит к вызову observeEvent для флажка, обновляя vals$current. При быстром нажатии кнопки Next это обновление перестает синхронизироваться c (т.е. со значением из предыдущего вызова updateCheckboxInput), так что кнопка Next observeEvent думает, что состояние флажка изменилось, когда оно не имеет.

Обратите внимание, что 1-секундный сон предназначен только для того, чтобы упростить работу - по сути, имитирует более медленные обновления (например, в нашем приложении для выставления оценок мы загружаем студента HTML или работу в формате PDF).

library(shiny)

stored_checks <- rep(c(TRUE, FALSE), 50)

ui <- fluidPage(
    checkboxInput("check", "Check"),
    actionButton("nextitem", "Next")
)

server <- function(session, input, output) {
    vals <- reactiveValues(item=1, current=stored_checks[1])
    observeEvent(input$check, { # update this check
        vals$current <- input$check

        Sys.sleep(1) # simulated slowdown of other observers etc
    }, ignoreInit = TRUE)
    observeEvent(input$nextitem, {
        if (vals$current != stored_checks[vals$item]) {
            cat("check has changed\n")
            stored_checks[vals$item] <- vals$current
        }
        vals$item <- vals$item %% 100 + 1
        vals$current <- stored_checks[vals$item]
        updateCheckboxInput(session, "check", value=vals$current)
    })
}

shinyApp(ui = ui, server = server)

Любые идеи приветствуются!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...