mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-10 07:28:01 -05:00
123 lines
4.4 KiB
R
123 lines
4.4 KiB
R
% Generated by roxygen2: do not edit by hand
|
|
% Please edit documentation in R/reactives.R
|
|
\name{debounce}
|
|
\alias{debounce}
|
|
\alias{throttle}
|
|
\title{Slow down a reactive expression with debounce/throttle}
|
|
\usage{
|
|
debounce(r, millis, priority = 100, domain = getDefaultReactiveDomain())
|
|
|
|
throttle(r, millis, priority = 100, domain = getDefaultReactiveDomain())
|
|
}
|
|
\arguments{
|
|
\item{r}{A reactive expression (that invalidates too often).}
|
|
|
|
\item{millis}{The debounce/throttle time window. You may optionally pass a
|
|
no-arg function or reactive expression instead, e.g. to let the end-user
|
|
control the time window.}
|
|
|
|
\item{priority}{Debounce/throttle is implemented under the hood using
|
|
\link[=observe]{observers}. Use this parameter to set the priority of
|
|
these observers. Generally, this should be higher than the priorities of
|
|
downstream observers and outputs (which default to zero).}
|
|
|
|
\item{domain}{See \link{domains}.}
|
|
}
|
|
\description{
|
|
Transforms a reactive expression by preventing its invalidation signals from
|
|
being sent unnecessarily often. This lets you ignore a very "chatty" reactive
|
|
expression until it becomes idle, which is useful when the intermediate
|
|
values don't matter as much as the final value, and the downstream
|
|
calculations that depend on the reactive expression take a long time.
|
|
\code{debounce} and \code{throttle} use different algorithms for slowing down
|
|
invalidation signals; see Details.
|
|
}
|
|
\details{
|
|
This is not a true debounce/throttle in that it will not prevent \code{r}
|
|
from being called many times (in fact it may be called more times than
|
|
usual), but rather, the reactive invalidation signal that is produced by
|
|
\code{r} is debounced/throttled instead. Therefore, these functions should be
|
|
used when \code{r} is cheap but the things it will trigger (downstream
|
|
outputs and reactives) are expensive.
|
|
|
|
Debouncing means that every invalidation from \code{r} will be held for the
|
|
specified time window. If \code{r} invalidates again within that time window,
|
|
then the timer starts over again. This means that as long as invalidations
|
|
continually arrive from \code{r} within the time window, the debounced
|
|
reactive will not invalidate at all. Only after the invalidations stop (or
|
|
slow down sufficiently) will the downstream invalidation be sent.
|
|
|
|
\verb{ooo-oo-oo---- => -----------o-}
|
|
|
|
(In this graphical depiction, each character represents a unit of time, and
|
|
the time window is 3 characters.)
|
|
|
|
Throttling, on the other hand, delays invalidation if the \emph{throttled}
|
|
reactive recently (within the time window) invalidated. New \code{r}
|
|
invalidations do not reset the time window. This means that if invalidations
|
|
continually come from \code{r} within the time window, the throttled reactive
|
|
will invalidate regularly, at a rate equal to or slower than the time
|
|
window.
|
|
|
|
\verb{ooo-oo-oo---- => o--o--o--o---}
|
|
}
|
|
\section{Limitations}{
|
|
|
|
|
|
Because R is single threaded, we can't come close to guaranteeing that the
|
|
timing of debounce/throttle (or any other timing-related functions in
|
|
Shiny) will be consistent or accurate; at the time we want to emit an
|
|
invalidation signal, R may be performing a different task and we have no
|
|
way to interrupt it (nor would we necessarily want to if we could).
|
|
Therefore, it's best to think of the time windows you pass to these
|
|
functions as minimums.
|
|
|
|
You may also see undesirable behavior if the amount of time spent doing
|
|
downstream processing for each change approaches or exceeds the time
|
|
window: in this case, debounce/throttle may not have any effect, as the
|
|
time each subsequent event is considered is already after the time window
|
|
has expired.
|
|
}
|
|
|
|
\examples{
|
|
## Only run examples in interactive R sessions
|
|
if (interactive()) {
|
|
options(device.ask.default = FALSE)
|
|
|
|
library(shiny)
|
|
library(magrittr)
|
|
|
|
ui <- fluidPage(
|
|
plotOutput("plot", click = clickOpts("hover")),
|
|
helpText("Quickly click on the plot above, while watching the result table below:"),
|
|
tableOutput("result")
|
|
)
|
|
|
|
server <- function(input, output, session) {
|
|
hover <- reactive({
|
|
if (is.null(input$hover))
|
|
list(x = NA, y = NA)
|
|
else
|
|
input$hover
|
|
})
|
|
hover_d <- hover \%>\% debounce(1000)
|
|
hover_t <- hover \%>\% throttle(1000)
|
|
|
|
output$plot <- renderPlot({
|
|
plot(cars)
|
|
})
|
|
|
|
output$result <- renderTable({
|
|
data.frame(
|
|
mode = c("raw", "throttle", "debounce"),
|
|
x = c(hover()$x, hover_t()$x, hover_d()$x),
|
|
y = c(hover()$y, hover_t()$y, hover_d()$y)
|
|
)
|
|
})
|
|
}
|
|
|
|
shinyApp(ui, server)
|
|
}
|
|
|
|
}
|