then function to access the eventual result of a promise (or, if the operation fails, the reason for that failure). Regardless of the state of the promise, the call to
then is non-blocking, that is, it returns immediately; so what it does not do is immediately return the result value of the promise. Instead, you pass logic you want to execute to
then, in the form of function callbacks (or formulas, see Details). If you provide an
onFulfilled callback, it will be called upon the promise's successful resolution, with a single argument
value: the result value. If you provide an
onRejected callback, it will be called if the operation fails, with a single argument
reason: the error that caused the failure.
then(promise, onFulfilled = NULL, onRejected = NULL) catch(promise, onRejected, tee = FALSE) finally(promise, onFinally)
A promise object. The object can be in any state.
A function (or a formula--see Details) that will be
invoked if the promise value successfully resolves. When invoked, the
function will be called with a single argument: the resolved value.
Optionally, the function can take a second parameter
.visible if you care
whether the promise was resolved with a visible or invisible value. The
function can return a value or a promise object, or can throw an error;
these will affect the resolution of the promise object that is returned
A function taking the argument
error (or a formula--see
Details). The function can return a value or a promise object, or can throw
an error. If
onRejected is provided and doesn't throw an error (or return
a promise that fails) then this is the async equivalent of catching an
TRUE, ignore the return value of the callback, and use the
original value instead. This is useful for performing operations with
side-effects, particularly logging to the console or a file. If the
callback itself throws an error, and
TRUE, that error will still
be used to fulfill the the returned promise (in other words,
tee only has
an effect if the callback does not throw).
A function with no arguments, to be called when the async operation either succeeds or fails. Usually used for freeing resources that were used during async operations.
For convenience, the
finally() functions use
rlang::as_function() to convert
onFinally arguments to functions. This means that you can use formulas to
create very compact anonymous functions, using
. to access the value (in
the case of
onFulfilled) or error (in the case of
The first parameter of
then is a promise; given the stated purpose of the
function, this should be no surprise. However, what may be surprising is that
the return value of
then is also a (newly created) promise. This new
promise waits for the original promise to be fulfilled or rejected, and for
onRejected to be called. The result of (or error raised
onRejected will be used to fulfill (reject) the
In this example, assuming
get_data_frame_async returns a promise that
eventually resolves to a data frame,
promise_b will eventually resolve to
the first 10 or fewer rows of that data frame.
Note that the new promise is considered fulfilled or rejected based on
onRejected returns a value or throws an error, not on
whether the original promise was fulfilled or rejected. In other words, it's
possible to turn failure to success and success to failure. Consider this
example, where we expect
some_async_operation to fail, and want to consider
it an error if it doesn't:
promise_d will be rejected if
promise_c is fulfilled, and vice
Warning: Be very careful not to accidentally turn failure into success, if your error handling code is not the last item in a chain!
In this example, the
catch callback does not itself throw an error, so the
then call will consider its promise fulfilled!
For readability and convenience, we provide
catch function is equivalent to
then, but without the
argument. It is typically used at the end of a promise chain to perform error
finally function is similar to
then, but takes a single no-argument
function (or formula) that will be executed upon completion of the promise,
regardless of whether the result is success or failure. It is typically used
at the end of a promise chain to perform cleanup tasks, like closing file
handles or database connections. Unlike
catch, the return value
finally is ignored; however, if an error is thrown in
error will be propagated forward into the returned promise.
onFulfilled functions can optionally have a second parameter
which will be
FALSE if the result value is invisible.