promises 1.4.0
Breaking changes
- Nested promise domains now correctly invoke in reverse order. Previously, when promise domains were nested, the outer domain would incorrectly take precedence over the inner domain in
wrapOnFulfilled/wrapOnRejectedcallbacks. The innermost (most recently added) domain now properly wraps the callback first, ensuring that nested promise domains behave consistently with the expected scoping behavior. (#165)
New features
-
hybrid_then()synchronously or asynchronously executes success/failure callbacks based on whether the input is a promise or a regular value. This function is useful for writing code that can handle both synchronous and asynchronous inputs seamlessly. (#192) -
then()gains ateeparameter. Whentee = TRUE,then()ignores the return value of the callback and returns the original value instead. This is useful for performing operations with side-effects, particularly logging to the console or a file.finally()does not supportteeas the return value is always ignored. (#148)
OpenTelemetry integration
promises now integrates with the otel package to provide observability and tracing for asynchronous operations. OpenTelemetry integration is experimental and subject to change.
-
with_ospan_async()creates an OpenTelemetry span, executes the given expression within it, and ends the span. This function handles both synchronous and asynchronous (promise-based) operations. For promises, the span is automatically ended when the promise resolves or rejects. To access the OpenTelemetry span within your expression, useotel::get_current_span(). (#173) -
with_ospan_promise_domain()creates a promise domain that restores the currently active OpenTelemetry span from when a call tothen()is executed. This enables proper tracing context across asynchronous operations. (#173) -
local_ospan_promise_domain()adds an OpenTelemetry span promise domain to the local scope. This is useful for{coro}operations where encapsulating the coro operations insidewith_*()methods is not allowed. (#179)
Minor improvements and fixes
-
promises now requires R 4.1 or later. R's native pipe (
|>) and function shorthand (\(x) fn(x)) syntax are now preferred over promise pipe methods. The promise pipe methods (%...>%,%...!%,%...T>%) are now superseded in favor of the R syntax supported in R 4.1 or later. (#148) -
catch()API updated fromcatch(promise, onRejected, tee = FALSE)tocatch(promise, onRejected, ..., tee = FALSE). Theteeparameter must now be specified as a keyword argument. (#148) -
then(tee=)andcatch(tee=)now require a logical value (not just a truthy value). (#156) -
promises is now a pure R package that does not require compilation. We include a test of a C++ interface in
inst/promise_task.cppthat is now dynamically compiled during testing. (#154) -
promise_all()performance improved by using a counter instead of checking completion status of all promises. This changes the time complexity fromO(n^2)toO(n)for determining when all promises are complete. (#163) -
promise_all()now preserves duplicate named arguments (or.listentries). A result will be produced for every promise provided. (#163) -
promise_map()now properly handlesNULLvalues being returned. (Thank you, @RLesur! #47) -
promises no longer imports base packages in DESCRIPTION. (Thank you, @shikokuchuo! #186)