In asynchronous JavaScript, it is easy to run tasks in parallel and wait for all of them to complete using Promise.all
:
async function bar(i) {
console.log('started', i);
await delay(1000);
console.log('finished', i);
}
async function foo() {
await Promise.all([bar(1), bar(2)]);
}
// This works too:
async function my_all(promises) {
for (let p of promises) await p;
}
async function foo() {
await my_all([bar(1), bar(2), bar(3)]);
}
I tried to rewrite the latter in python:
import asyncio
async def bar(i):
print('started', i)
await asyncio.sleep(1)
print('finished', i)
async def aio_all(seq):
for f in seq:
await f
async def main():
await aio_all([bar(i) for i in range(10)])
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
But it executes my tasks sequentially.
What is the simplest way to await multiple awaitables? Why doesn't my approach work?
The equivalent would be using asyncio.wait
:
import asyncio
async def bar(i):
print('started', i)
await asyncio.sleep(1)
print('finished', i)
async def main():
await asyncio.wait([bar(i) for i in range(10)])
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
Why doesn't my approach work?
Because when you await
each item in seq
, you block that coroutine. So in essence, you have synchronous code masquerading as async. If you really wanted to, you could implement your own version of asyncio.wait
using loop.create_task
or asyncio.ensure_future
.
EDIT
As Andrew mentioned, you can also use asyncio.gather
.