1

Is there some way to call asynchronous function in NOT for loop (e.g. foreach, map) using async/await and continue execution of the rest code only after all asynchronous functions completed?

const layers = ["layer1", "layer2", "layer3"];

async function connect(layer: string): Promise<object> {
    return new Promise((resolve, reject) => {
        setTimeout(function () {
            resolve(layer);
        }, 1000);
    });
}

(async function () {
    for (let i = 0; i < layers.length; i++) {
        const result = await connect(layers[i]);
        console.log(result, "connected");
    }
    console.log("All layers are connected");
})();
vich
  • 262
  • 2
  • 15
  • 1
    Possible duplicate of [Using async/await with a forEach loop](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop) – sagi Oct 10 '18 at 06:49

3 Answers3

3

You are looking for Promise.all(). It gets an array (or other iterable object) of Promises and returns a new Promise that resolves when all the input Promises resolve. The input Promises are executed in parallel (much better than await-ing for each Promise in a loop).

You await this Promise.

const layers = ["layer1", "layer2", "layer3"];

async function connect(layer: string): Promise<object> {
    return new Promise((resolve, reject) => {
        setTimeout(function () {
            resolve(layer);
        }, 1000);
    });
}

await Promise.all(layers.map(connect));
console.log('All layers are connected');
axiac
  • 68,258
  • 9
  • 99
  • 134
1

Technically speaking you "can", but you don't want to. If you have a collection of promises you need to resolve, it's best to resolve them with Promise.all().

dvsoukup
  • 1,586
  • 15
  • 31
0

It is possible to use await in async function. And thus, to use it with other statements that are used in async besides for, namely do..while and while loop statements.

Is there some way to call asynchronous function in NOT for loop (e.g. foreach, map)

This is a different case. Callback-based methods like forEach have their own functions. It's impossible to use await inside regular function:

arr.forEach(() => {
  await ... // syntax error
});

Using async function together with await with forEach is a common mistake because it results in a promise that is ignored:

arr.forEach(async () => {
  await ... // isn't awaited outside function
});

It's acceptable to use async..await with map because of the way it works, a promise that is returned from async is used by map and mapped to resulting array:

const arrOfPromises = arr.map(async () => {
  await ...
});

Promises should be explicitly chained in order to be awaited outside map function:

await Promise.all(arrOfPromises);
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Looks like map() will not work in this case. `(async function () { const results = layers.map(async (layer) => { const result = await connect(layer); console.log(result, "connected"); return result; }); console.log("All layers are connected", results); })();` Result of this code is: `All layers are connected [ Promise { }, Promise { }, Promise { } ] layer1 connected layer2 connected layer3 connected` – vich Oct 10 '18 at 08:52
  • The code doesn't contain `map`. But you should have `result = await Promise.all(promises)` at some point. Like I said, *Promises should be explicitly chained in order to be awaited outside map function*. `async` is syntactic sugar for promises. Promises cannot resolve synchronously by magic. – Estus Flask Oct 10 '18 at 08:56
  • yep, sorry. got it. it works with Promise.all(); So, using Promise.all() is the best way to work with collection of async functions? what are the disadvantages using `for` loop as it shown in my question? performance? – vich Oct 10 '18 at 09:02
  • 1
    *with collection of async functions* - with a collection of promises, to be precise. `map` calls functions and returns promises from them. Yes, the difference is performance. `map` with `await Promise.all` is the recipe for concurrent promises. `for` with `await` is the recipe for sequential promises. If promises don't depend on each other and don't create problems (100 concurrent requests at once) then concurrency is preferable. – Estus Flask Oct 10 '18 at 09:07