Implement reactive domains

This commit is contained in:
Joe Cheng
2014-04-07 17:44:26 -07:00
committed by Joe Cheng
parent 29c0f9a43a
commit e5e54fe4c1
17 changed files with 446 additions and 54 deletions

53
man/domains.Rd Normal file
View File

@@ -0,0 +1,53 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
\name{getDefaultReactiveDomain}
\alias{domains}
\alias{getDefaultReactiveDomain}
\alias{onReactiveDomainEnded}
\alias{withReactiveDomain}
\title{Reactive domains}
\usage{
getDefaultReactiveDomain()
withReactiveDomain(domain, expr)
onReactiveDomainEnded(domain, callback, failIfNull = FALSE)
}
\arguments{
\item{domain}{A valid domain object (for example, a Shiny session), or
\code{NULL}}
\item{expr}{An expression to evaluate under \code{domain}}
\item{callback}{A callback function to be invoked}
\item{failIfNull}{If \code{TRUE} then an error is given if the \code{domain}
is \code{NULL}}
}
\description{
Reactive domains are a mechanism for establishing ownership over reactive
primitives (like reactive expressions and observers), even if the set of
reactive primitives is dynamically created. This is useful for lifetime
management (i.e. destroying observers when the Shiny session that created
them ends) and error handling.
}
\details{
At any given time, there can be either a single "default" reactive domain
object, or none (i.e. the reactive domain object is \code{NULL}). You can
access the current default reactive domain by calling
\code{getDefaultReactiveDomain}.
Unless you specify otherwise, newly created observers and reactive
expressions will be assigned to the current default domain (if any). You can
override this assignment by providing an explicit \code{domain} argument to
\code{\link{reactive}} or \code{\link{observe}}.
For advanced usage, it's possible to override the default domain using
\code{withReactiveDomain}. The \code{domain} argument will be made the
default domain while \code{expr} is evaluated.
Implementers of new reactive primitives can use \code{onReactiveDomainEnded}
as a convenience function for registering callbacks. If the reactive domain
is \code{NULL} and \code{failIfNull} is \code{FALSE}, then the callback will
never be invoked.
}

View File

@@ -4,13 +4,14 @@
\title{Create a reactive observer}
\usage{
observe(x, env = parent.frame(), quoted = FALSE, label = NULL,
suspended = FALSE, priority = 0)
suspended = FALSE, priority = 0, domain = getDefaultReactiveDomain())
}
\arguments{
\item{x}{An expression (quoted or unquoted). Any return value will be ignored.}
\item{x}{An expression (quoted or unquoted). Any return value will be
ignored.}
\item{env}{The parent environment for the reactive expression. By default, this
is the calling environment, the same as when defining an ordinary
\item{env}{The parent environment for the reactive expression. By default,
this is the calling environment, the same as when defining an ordinary
non-reactive expression.}
\item{quoted}{Is the expression quoted? By default, this is \code{FALSE}.
@@ -26,6 +27,8 @@ If \code{FALSE} (the default), start in a non-suspended state.}
this observer should be executed. An observer with a given priority level
will always execute sooner than all observers with a lower priority level.
Positive, negative, and zero values are allowed.}
\item{domain}{See \code{\link{domains}}.}
}
\value{
An observer reference class object. This object has the following
@@ -42,6 +45,10 @@ An observer reference class object. This object has the following
invalidations. If the observer was invalidated while suspended, then it
will schedule itself for re-execution.
}
\item{\code{destroy()}}{
Stops the observer from executing ever again, even if it is currently
scheduled for re-execution.
}
\item{\code{setPriority(priority = 0)}}{
Change this observer's priority. Note that if the observer is currently
invalidated, then the change in priority will not take effect until the
@@ -59,19 +66,23 @@ An observer reference class object. This object has the following
Creates an observer from the given expression.
}
\details{
An observer is like a reactive
expression in that it can read reactive values and call reactive expressions, and
will automatically re-execute when those dependencies change. But unlike
reactive expressions, it doesn't yield a result and can't be used as an input
to other reactive expressions. Thus, observers are only useful for their side
effects (for example, performing I/O).
An observer is like a reactive expression in that it can read reactive values
and call reactive expressions, and will automatically re-execute when those
dependencies change. But unlike reactive expressions, it doesn't yield a
result and can't be used as an input to other reactive expressions. Thus,
observers are only useful for their side effects (for example, performing
I/O).
Another contrast between reactive expressions and observers is their execution
strategy. Reactive expressions use lazy evaluation; that is, when their
dependencies change, they don't re-execute right away but rather wait until
they are called by someone else. Indeed, if they are not called then they
will never re-execute. In contrast, observers use eager evaluation; as soon
as their dependencies change, they schedule themselves to re-execute.
Another contrast between reactive expressions and observers is their
execution strategy. Reactive expressions use lazy evaluation; that is, when
their dependencies change, they don't re-execute right away but rather wait
until they are called by someone else. Indeed, if they are not called then
they will never re-execute. In contrast, observers use eager evaluation; as
soon as their dependencies change, they schedule themselves to re-execute.
Starting with Shiny 0.10.0, observers are automatically destroyed by default
when the \code{\link{domain}} that owns them ends (e.g. when a Shiny session
ends).
}
\examples{
values <- reactiveValues(A=1)

View File

@@ -4,7 +4,8 @@
\alias{reactive}
\title{Create a reactive expression}
\usage{
reactive(x, env = parent.frame(), quoted = FALSE, label = NULL)
reactive(x, env = parent.frame(), quoted = FALSE, label = NULL,
domain = getDefaultReactiveDomain())
is.reactive(x)
}
@@ -21,6 +22,8 @@ This is useful when you want to use an expression that is stored in a
variable; to do so, it must be quoted with `quote()`.}
\item{label}{A label for the reactive expression, useful for debugging.}
\item{domain}{See \code{\link{domains}}.}
}
\value{
a function, wrapped in a S3 class "reactive"