Reputation: 891
I need to resolve all promises in an array of json, like this:
let list = [
{
id: 1,
data: new Promise((resolve, reject) => {
resolve('Cat')
})
},
{
id: 2,
data: new Promise((resolve, reject) => {
resolve('Dog')
})
},
{
id: 3,
data: new Promise((resolve, reject) => {
resolve('Mouse')
})
}
]
I use bluebird promises. I used a for cycle to iterate all items, I would know if there was some way more elegant.
Expected result:
[ { data: 'Cat', id: 1 },
{ data: 'Dog', id: 2 },
{ data: 'Mouse', id: 3 } ]
Upvotes: 1
Views: 8344
Reputation: 2313
Resolve Promise.all() to an actual usable array of JSON.
The problem: Promise.all() resolves to an array of resolved promises. To see why this is an issue, copy and paste this into your console:
var promise1 = fetch('https://swapi.dev/api/people/2'); // C-3PO
var promise2 = fetch('https://swapi.dev/api/people/3'); // R2-D2
Promise.all([promise1, promise2])
.then(res => console.log(res)); // resolved promises - trash...
See how there's no actual usable data in those resolved promises..? On the web, you need to call another promise to convert them to text or html or, most likely, beloved json. But how can you do this efficiently?
Well, then solution to our Promise.all() issue is... more Promise.all()!!!
Example:
var promise3 = fetch('https://swapi.dev/api/people/1'); // Luke
var promise4 = fetch('https://swapi.dev/api/people/4'); // Luke's daddy
Promise.all([promise3, promise4])
.then(res => Promise.all([res[0].json(), res[1].json()]))
.then(res => console.log(res)); // real data :)
Hope this helps someone! Thanks!
Upvotes: 2
Reputation: 5801
you can use lodash lib to minimize your code
const _ = require('lodash');
Promise.all(_.map(list, 'data')).then((data)=>{
list.map((item,ind)=>{item.data = data[ind]});
console.log(list);
})
Upvotes: 0
Reputation: 1
This should work, Promise.all and array.map like the others, but the result is correct
let list = [
{
id: 1,
data: new Promise((resolve, reject) => {
resolve('Cat')
})
},
{
id: 2,
data: new Promise((resolve, reject) => {
resolve('Dog')
})
},
{
id: 3,
data: new Promise((resolve, reject) => {
resolve('Mouse')
})
}
]
Promise.all(list.map(item => item.data.then(data => ({...item, data}))))
// that's it, that's what you want, the rest is for show now
.then(results => {
console.log(results);
});
though, that's Native Promises ... you may want to look into Promise.props and/or Promise.map in bluebird for possibly simpler code yet
It could well be as simple as
Promise.map(list, Promise.props)
.then(results => {
console.log(results);
});
tested the above, and yes, it is that simple - the snippet below has my own version of
Promise.map
andPromise.props
- and works (at least in this case) identically to bluebird
Promise.props = obj => {
const keys = Object.keys(obj);
return Promise.all(Object.values(obj)).then(results => Object.assign({}, ...results.map((result, index) => ({[keys[index]]: result}))));
};
Promise.map = (array, fn, thisArg) => Promise.all(Array.from(array, (...args) => fn.apply(thisArg, args)));
let list = [
{
id: 1,
data: new Promise((resolve, reject) => {
resolve('Cat')
})
},
{
id: 2,
data: new Promise((resolve, reject) => {
resolve('Dog')
})
},
{
id: 3,
data: new Promise((resolve, reject) => {
resolve('Mouse')
})
}
]
Promise.map(list, Promise.props)
.then(results => {
console.log(results);
});
Upvotes: 7
Reputation: 722
You just need create an array of promises. you can do it with for
or map
let promises = []
for(var i=0; i < list.length; i++)
promises.push(list.data)
Promise.all(promises).then(resultList => { ... }).catch(err => { ... })
or simplest may with map
Promise.all(list.map(p => p.data)).then(resultList => { ... }).catch(err => { ... })
Upvotes: 0
Reputation: 952
With Promise.all
& some JavaScript.
let list = [];
let promise = Promise.all(list.map(entry => entry.data));
promise.then((results) => {
let final = results.map((result, index) => {
return {data: result, id: list[index].id};
});
console.log(final);
});
Upvotes: 1
Reputation: 48807
Promise.all
may be a good fit here:
Promise.all(list.map(entry => entry.data)).then((resolved) => {
// ...
});
Upvotes: 0