Promise domains are used to temporarily set up custom environments that
intercept and influence the registration of callbacks. Create new promise
domain objects using new_promise_domain, and temporarily activate a promise
domain object (for the duration of evaluating a given expression) using
with_promise_domain.
with_promise_domain(domain, expr, replace = FALSE)new_promise_domain(
wrapOnFulfilled = identity,
wrapOnRejected = identity,
wrapSync = force,
onError = force,
...,
wrapOnFinally = NULL
)
A promise domain object to install while expr is evaluated.
Any R expression, to be evaluated under the influence of
domain.
If FALSE, then the effect of the domain will be added
to the effect of any currently active promise domain(s). If TRUE, then
the current promise domain(s) will be ignored for the duration of the
with_promise_domain call.
A function that takes a single argument: a function
that was passed as an onFulfilled argument to then(). The
wrapOnFulfilled function should return a function that is suitable for
onFulfilled duty.
A function that takes a single argument: a function
that was passed as an onRejected argument to then(). The
wrapOnRejected function should return a function that is suitable for
onRejected duty.
A function that takes a single argument: a (lazily evaluated)
expression that the function should force(). This expression represents
the expr argument passed to with_promise_domain();
wrapSync allows the domain to manipulate the environment before/after
expr is evaluated.
A function that takes a single argument: an error. onError
will be called whenever an exception occurs in a domain (that isn't caught
by a tryCatch). Providing an onError callback doesn't cause errors to
be caught, necessarily; instead, onError callbacks behave like calling
handlers.
Arbitrary named values that will become elements of the promise
domain object, and can be accessed as items in an environment (i.e. using
[[ or $).
A function that takes a single argument: a function
that was passed as an onFinally argument to then(). The
wrapOnFinally function should return a function that is suitable for
onFinally duty. If wrapOnFinally is NULL (the default), then the
domain will use both wrapOnFulfilled and wrapOnRejected to wrap the
onFinally. If it's important to distinguish between normal
fulfillment/rejection handlers and finally handlers, then be sure to
provide wrapOnFinally, even if it's just base::identity().
While with_promise_domain is on the call stack, any calls to
then() (or higher level functions or operators, like
catch()) will belong to the promise domain. In addition, when a
then callback that belongs to a promise domain is invoked, then any new
calls to then will also belong to that promise domain. In other words, a
promise domain "infects" not only the immediate calls to then, but also to
"nested" calls to then.
For more background, read the original design doc.
For examples, see the source code of the Shiny package, which uses promise domains extensively to manage graphics devices and reactivity.