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()
or the various pipes)
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.