Skip to contents

Promises Integration

mirai supplies its own as.promise() method, allowing it to be used as a promise from the promises package.

These are next-generation, event-driven promises, developed in collaboration with Joe Cheng.

  • Do not require each promise to be polled for completion by a later loop like other promises.
  • Instead, promise actions are automatically queued for execution as soon as each ‘mirai’ resolves.
  • Allows for much higher responsiveness (lower latency) and massive scalability (situations with thousand of promises or more).

A ‘mirai’ may be piped directly using the promise pipe &...>%, which implicitly calls as.promise() on the ‘mirai’. Similarly all promise-aware functions such as promises::then() or shiny::ExtendedTask$new() which take a promise can also take a ‘mirai’ (using promises >= 1.3.0).

Alternatively, a ‘mirai’ may be explicitly converted into a promise by as.promise(), which then allows using the methods $then(), $finally() etc.

The following example outputs “hello” to the console after one second when the ‘mirai’ resolves.


p <- mirai({Sys.sleep(1); "hello"}) %...>% cat()
#> <Promise [pending]>

It is possible to both access a ‘mirai’ value at $data and to use a promise for enacting a side effect (assigning the value to an environment in the example below).

env <- new.env()

m <- mirai({

promises::then(m, function(x) env$res <- x)

#> [1] "hello"

After returning to the top level prompt:

#> [1] "hello"

The One Million Promises Challenge

The code below is taken from the challenge to launch and collect one million promises. For illustration, the example is scaled down to one thousand.

daemons(8, dispatcher = FALSE)
#> [1] 8
r <- 0
start <- Sys.time()
m <- mirai_map(1:1000, \(x) x, .promise = \(x) r <<- r + x)
Sys.time() - start
#> Time difference of 0.2646537 secs
#> [1] 500500
#> [1] 0

The one million promises challenge took 6 mins 25 secs to complete using an Intel i7 11th gen mobile processor with 16GB RAM.