Hedge
Hedge

Reputation: 16748

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?

Upvotes: 5

Views: 6039

Answers (5)

andrasi
andrasi

Reputation: 11

You can redefine the iterator on your map like this:

myMap[Symbol.iterator] = function* () {
  yield this.get("foo");
  yield this.get("foo2");
};

after that You can use your Map with Promise.all():

let result = await Promise.all(myMap);

Upvotes: 1

Bergi
Bergi

Reputation: 664454

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));
}());

Upvotes: 6

Jaromanda X
Jaromanda X

Reputation: 1

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

Upvotes: 7

Estus Flask
Estus Flask

Reputation: 222464

It is

const myArr = [...myMap.entries()].map(([key, value]) => {
  return MyModel.forge({key, language, value}).save()
});

Promise.all(myArr);

Upvotes: 1

Joseph
Joseph

Reputation: 119847

You can use Array.from() to convert a Map to an array of pairs, key first, value second. Then use array.map to construct your array of promises to feed to Promise.all.

var pairs = Array.from(myMap); // [['foo', 'bar'], ['foo2', 'bar42']]

Upvotes: 3

Related Questions