简体   繁体   中英

Resolve all promises in an array of json - javascript

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 } ]

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 and Promise.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); }); 

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

Promise.all may be a good fit here:

Promise.all(list.map(entry => entry.data)).then((resolved) => {
  // ...
});

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 => { ... })

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

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.co/api/people/2'); // C-3PO
var promise2 = fetch('https://swapi.co/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.co/api/people/1'); // Luke
var promise4 = fetch('https://swapi.co/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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM