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.
Usage
with_promise_domain(domain, expr, replace = FALSE)
new_promise_domain(
wrapOnFulfilled = identity,
wrapOnRejected = identity,
wrapSync = force,
onError = force,
...,
wrapOnFinally = NULL
)Arguments
- domain
A promise domain object to install while
expris evaluated.- expr
Any R expression, to be evaluated under the influence of
domain.- replace
If
FALSE, then the effect of thedomainwill be added to the effect of any currently active promise domain(s). IfTRUE, then the current promise domain(s) will be ignored for the duration of thewith_promise_domaincall.- wrapOnFulfilled
A function that takes a single argument: a function that was passed as an
onFulfilledargument tothen(). ThewrapOnFulfilledfunction should return a function that is suitable foronFulfilledduty.- wrapOnRejected
A function that takes a single argument: a function that was passed as an
onRejectedargument tothen(). ThewrapOnRejectedfunction should return a function that is suitable foronRejectedduty.- wrapSync
A function that takes a single argument: a (lazily evaluated) expression that the function should
force(). This expression represents theexprargument passed towith_promise_domain();wrapSyncallows the domain to manipulate the environment before/afterexpris evaluated.- onError
A function that takes a single argument: an error.
onErrorwill be called whenever an exception occurs in a domain (that isn't caught by atryCatch). Providing anonErrorcallback doesn't cause errors to be caught, necessarily; instead,onErrorcallbacks 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$).- wrapOnFinally
A function that takes a single argument: a function that was passed as an
onFinallyargument tothen(). ThewrapOnFinallyfunction should return a function that is suitable foronFinallyduty. IfwrapOnFinallyisNULL(the default), then the domain will use bothwrapOnFulfilledandwrapOnRejectedto wrap theonFinally. If it's important to distinguish between normal fulfillment/rejection handlers and finally handlers, then be sure to providewrapOnFinally, even if it's justbase::identity().
Details
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.