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
?
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.
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.
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.
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.
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:
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.
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 ...
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?
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
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));
}());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With