In JavaScript there is Promise.all
to wait at once for several futures. Is there (or can be implemented?) a similar thing in Motoko?
I want to wait for skExists
from several CanDB canisters to securely check whether a key exists in the CanDB DB. Is it possible?
1 Like
There is no Promise.all in Motoko and it’s currently not possible to author a fully generic one.
However, you can do parallel waiting by issuing several sends and only awaiting the results later.
‘’’
let p1 = a1.send();
let p2 = a2.send();
let r1 = await p1;
let r2 = await p2;
‘’’
2 Likes
No, @claudio , your code first blocks on await p1
and only then moves to await p2
.
Probably, this will work:
let p1 = a1.send();
let p2 = a2.send();
let r = [await p1, await p2];
But I am unsure even on the last code.
quint
May 17, 2023, 7:17pm
4
That is exactly how a Promise.all
works.
You will only be waiting as long as the longest call.
Either p1
takes longer, than you do not need to wait on p2
.
Or p1
finishes and you will also have to wait for p2
.
There is no real difference between:
1 Like
@claudio You seem to think that
let r1 = await p1;
let r2 = await p2;
executes in parallel.
That’s not the case! await
like any other language construct is executed sequentially.
await p1
blocks that is not allows to execute any more code in this thread of control until p1
finished. Only then await p2
is executed.
I will present another example to illustrate my point:
let r1 = await p1;
Debug.print("in the middle");
let r2 = await p2;
If await p2
executed in parallel with await p1
, then in the middle
would be printed after await p2
, not before. That’s not the case.
@claudio Oh, I misunderstood you:
await p1;
await p2;
is really equivalent to Promise.all
in JavaScript, because it finishes as soon as both p1
and p2
finish.
@claudio
However, no:
a1.send()
does not start execution of an async function a1.send
, it just returns a future (if Motoko works the same as most asynchronous languages).
So, in
let p1 = a1.send();
let p2 = a2.send();
let r1 = await p1;
let r2 = await p2;
execution of a2
starts only after execution of a1
finishes.
1 Like
Both messages are enqueued at send() and actually both sent at the first await. If destined at two different receivers, they can execute concurrently and, after the second await, will both have finished.
Motoko futures are eager, not lazy. Even if you don’t await a future, its effects still happen.