Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Promise.all on the entries of a Map()

I am using a Map for some key/value pairs

let myMap = new Map()
myMap.set('foo', 'bar')
myMap.set('foo2', 'bar42')

For every Map entry I execute a function which returns a Promise. All these Promises can be executed in parallel using Promise.all.

This is how I do it right now:

let mapPromises = []
myMap.forEach((value, key) => {
  mapPromises.push(MyModel.forge({key, language, value}).save())
})
await Promise.all(mapPromises)

Is there another (shorter?, faster?) approach to accomplish this than pushing all function calls into an array and then triggering Promise.all?

like image 232
Hedge Avatar asked Mar 27 '17 22:03

Hedge


People also ask

How do you use promises on a map?

map. Given a finite Iterable (arrays are Iterable ), or a promise of an Iterable , which produces promises (or a mix of promises and values), iterate over all the values in the Iterable into an array and map the array to another using the given mapper function.

What is the use of Promise all ()?

The Promise. all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will fulfill when all of the input's promises have fulfilled, or if the input iterable contains no promises.

How Use Promise all in async function?

Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

Can I use async await with Promise all ()?

all() with async-await. Example 1: In this example we will creating two promises inside two different functions (or methods) and in another function we will accessing them using Promise. all() along with making that function as async and promise resulting fetching will be done along with the await keyword.

Why does the map method return an array of promises?

But recall that async functions always return a promise. As a result, you are returning an array of promises. To summarize: the map method is a synchronous operation, but we are trying to do something asynchronous here, which combined with async/await leads to an array of promises instead of values. The solution here is to use Promise.all, like so:

How do I map a promise?

A Promise is a bit special since it doesn’t have a proper map method. Rather its then method behaves much like the map method. Let’s see it in practice: Let’s go over snippet #4 line by line and make sense of it. We start by defining our projection function, getUserName, which gets a user object and returns its name property.

What is the use of promise all in JavaScript?

JavaScript | Promise.all () Method. The Promise.all () method is actually a promise that takes an array of promises (an iterable) as an input. It returns a single Promise that resolves when all of the promises passed as an iterable, which have resolved or when the iterable contains no promises. In simple way, if any of the passed-in promises ...

How to return only one promise from an array of promises?

The solution here is to use Promise.all, like so: Promise.all is designed to take an array of promises as input and returns only one promise after all input promises have resolved, meaning the output will be one of values. Are you sure you want to hide this comment?


2 Answers

The simplest code I could come up with is

await Promise.all(Array.from(myMap, ([key, value]) => 
    MyModel.forge({key, language, value}).save())
);

See Array#from documentation

like image 156
Jaromanda X Avatar answered Oct 02 '22 20:10

Jaromanda X


Yes, using forEach and manually pushing to an array is almost always a bad idea.

You can directly create the array from the map, mapping over it in the process:

async function processEntry([key, value]) {
    return MyModel.forge({key, value}).save();
}

(async function() {
    let myMap = new Map()
    myMap.set('foo', 'bar')
    myMap.set('foo2', 'bar42')

    const results = await Promise.all(Array.from(myMap, processEntry));
}());

But if you want to use an iterator, you also can do something like

function* processEntries(map) {
    for (const [key, value] of map)
        yield MyModel.forge({key, value}).save();
}

(async function() {
    let myMap = new Map()
    myMap.set('foo', 'bar')
    myMap.set('foo2', 'bar42')

    const results = await Promise.all(processEntries(myMap));
}());
like image 36
Bergi Avatar answered Oct 02 '22 18:10

Bergi