In Opal 1.2 we introduced PromiseV2 which is to replace the default Promise in Opal 2.0 (which will become PromiseV1). Right now it's experimental, but the interface of PromiseV1 stay unchanged and will continue to be supported.
It is imperative that during the transition period you either
require 'promise/v1' or
require 'promise/v2' and then use either
If you write library code it's imperative that you don't require the promise itself, but
PromiseV2 is defined and use the newer implementation, for instance using the
module MyLibrary Promise = defined?(PromiseV2) ? PromiseV2 : ::Promise end
The difference between
PromiseV2 is that
PromiseV1 is a pure-Ruby
implementation of a Promise, while
Promise. Both are
incompatible with each other, but
PromiseV2 can be awaited (see below) and they translate
Promise (they are bridged; you can directly return a
PromiseV2 always runs a
#then block a tick later, while
PromiseV1 would could run it
In Opal 1.3 we implemented the CoffeeScript pattern of async/await. As of now, it's hidden behind a magic comment, but this behavior may change in the future.
# await: true require "await" def wait_5_seconds puts "Let's wait 5 seconds..." sleep(5).__await__ puts "Done!" end wait_5_seconds.__await__
It's important to understand what happens under the hood: every scope in which
encountered will become async, which means that it will return a PromiseV2 that will resolve
to a value. This includes methods, blocks and the top scope. This means, that
infectious and you need to remember to
#__await__ everything along the way, otherwise
a program will finish too early and the values may be incorrect.
It is certainly correct to
#__await__ any value, including non-Promises, for instance
5.__await__ will correctly resolve to
5 (except that it will make the scope an async
function, with all the limitations described above).
await stdlib module includes a few useful functions, like async-aware
sleep that doesn't block the thread. It also includes a method
which is an alias of
#itself - it makes sense to auto-await that method.
This approach is certainly incompatible with what Ruby does, but due to a dynamic nature
Promise heavy APIs and asynchronous code.
The magic comment also accepts a comma-separated list of methods to be automatically
awaited. An individual value can contain a wildcard character
*. For instance,
those two blocks of code are equivalent:
# await: true require "await" [1,2,3].each_await do |i| p i sleep(i).__await__ end.__await__
# await: sleep, *await* require "await" [1,2,3].each_await do |i| p i sleep i end