JS Promises: is there an optional way to resolve multiple promises as properties of an object?
I wrote the code below and then realized what it resolved before (registration before all promises resolve):
readDirPromise
.then(categoriseFiles)
.then(({movies, series}) => ({
movies: Promise.all(movies.map(movieTasks)),
series: Promise.all(series.map(seriesTasks))
}))
.then((res) => {
console.log('🦄 done!', res)
})
I was able to rewrite it to resolve it in the correct order:
readDirPromise
.then(categoriseFiles)
.then((cats) => Promise.all(cats.movies.map(movieTasks)).then((movies) => {
cats.movies = movies
return cats
}))
.then((cats) => Promise.all(cats.series.map(seriesTasks)).then((series) => {
cats.series = series
return cats
}))
.then((res) => {
console.log('🦄 done!', res)
})
but I can't help but think ... is there a neater, more extensible way?
You can make the serial step independent of the video step (rather than block one by one) by wrapping both of them on a different layer Promise.all
, returning as a tuple, which you can then destruct and rebuild into the object you want:
readDirPromise
.then(categoriseFiles)
.then(({movies, series}) => Promise.all([
Promise.all(movies.map(movieTasks)),
Promise.all(series.map(seriesTasks))])
.then(([movies, series]) => ({movies, series}))
.then((res) => {
console.log('🦄 done!', res)
})
For what it's worth, I believe the async / await version would look something like this:
async function generateResponse() {
const {movies, series} = await readDirPromise.then(categoriseFiles);
return {
movies: await Promise.all(movies.map(movieTasks)),
series: await Promise.all(series.map(seriesTasks))
}
}
Instead of chaining promises, you can create separate promises and resolve them in the method Promise.all
as you did.
var p1 = getNewPromise();
var p2 = getNewPromise();
var p3 = getNewPromise();
// From MDN
Promise.all([p1, p2, p3]).then(values => {
console.log(values);
});