Skip to content

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/wrapOnRejected callbacks. 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 a tee parameter. When tee = 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 support tee as 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, use otel::get_current_span(). (#173)

  • with_ospan_promise_domain() creates a promise domain that restores the currently active OpenTelemetry span from when a call to then() 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 inside with_*() 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 from catch(promise, onRejected, tee = FALSE) to catch(promise, onRejected, ..., tee = FALSE). The tee parameter must now be specified as a keyword argument. (#148)

  • then(tee=) and catch(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.cpp that 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 from O(n^2) to O(n) for determining when all promises are complete. (#163)

  • promise_all() now preserves duplicate named arguments (or .list entries). A result will be produced for every promise provided. (#163)

  • promise_map() now properly handles NULL values being returned. (Thank you, @RLesur! #47)

  • promises no longer imports base packages in DESCRIPTION. (Thank you, @shikokuchuo! #186)

promises 1.3.3

CRAN release: 2025-05-29

  • Changed the way we create future objects to stay compatible with new versions of future. Apparently the way we were doing it was never idiomatic and only worked by accident. (#121)

  • Fixed #122: Use future::future(..., lazy = TRUE) to avoid manual capturing of state within future_promise (Thank you, @HenrikBengtsson! #123)

promises 1.3.2

CRAN release: 2024-11-27

  • Fixed bug introduced in 1.3.1, where promise domains that are active at promise resolution time stay active during handler callback, even if they weren’t active when the handler was registered. This was causing stack overflow for long promise chains with many active promise domains. (#115)

promises 1.3.1

CRAN release: 2024-11-26

  • Fixed bug where promise domains were forgotten when handlers were registered from within other handlers. (#110)

promises 1.3.0

CRAN release: 2024-04-05

  • is.promising is now an S3 method. (#104)

promises 1.2.1

CRAN release: 2023-08-10

promises 1.2.0.1

CRAN release: 2021-02-11

promises 1.1.1

CRAN release: 2020-06-09

promises 1.1.0

CRAN release: 2019-10-04

  • Fixed #49: promise_all() previously did not handle NULL values correctly. (#50)

  • new_promise_domain now takes a wrapOnFinally argument, which can be used to intercept registration of finally(). Previous versions treated finally as passing the same callback to then(onFulfilled=..., onRejected=...), and ignoring the result; for backward compatibility, promise domains will still treat finally that way by default (i.e. if wrapOnFinally is NULL, then finally will result in wrapOnFulfilled and wrapOnRejected being called, but if wrapOnFinally is provided then only wrapOnFinally will be called). (#43)

promises 1.0.1

CRAN release: 2018-04-13

  • Initial CRAN release