Reputation: 5376
I have an array of objects that looks like this:
[ { firstName: 'Mike', lastName: 'Jones' },
{ firstName: 'Joe', lastName: 'Smith' },
{ firstName: 'Bob', lastName: 'Johnson' } ]
I need to pass that array to a function that's going to add a "middleName" field to each object, and a value for middleName. The function gets the middle name by making an asynchronous http.get request in Node. And therein lies the problem. I can't make this work no matter how I try.
Previously someone suggested a loop like this:
array.forEach(function (obj) {
GetMiddleName(obj, function (person) {
obj.MiddleName = person;
});
});
But that doesn't work due to the async nature of the get being called in the GetMiddleName function. Can anyone show me a short, simple function that will do what I need?
Upvotes: 0
Views: 590
Reputation: 1140
You need to create an array of promises and then resolve them. I think some of the answers here are correct but this is cleaner and easier to understand, especially if you are new to promises.
let promises = [];
array.forEach(function (item) {
let promise = new Promise(function (resolve) {
GetMiddleName(obj, function (person) {
obj.MiddleName = person;
resolve();
});
});
promises.push(promise);
});
Promise.all(promises).then(function () {
// Do something after all values/promises have been resolved
// If not just leave it at Promise.all(promises)
});
Upvotes: 0
Reputation: 688
You could use the async
package to handle asynchronous iterations by using the async framework.
Using async.eachOf
without callback function (returns promise). Note: available from version 3.x.
Returns:
a promise, if a callback is omitted
Type: Promise
const async = require('async');
let items = [
{ firstName: 'Mike', lastName: 'Jones' },
{ firstName: 'Joe', lastName: 'Smith' },
{ firstName: 'Bob', lastName: 'Johnson' }
];
async.eachOf(items, (item, index, callback) => {
GetMiddleName(item, function (person) {
item.MiddleName = person;
})
.then(result => {
console.log('this is result:', result);
callback();
});
})
.then(() => {
console.log('All items updated');
});
Or you can handle it with callback function like this:
async.eachOf(items, (item, index, callback) => {
GetMiddleName(item, function (person) {
item.MiddleName = person;
})
.then(result => {
console.log('this is result:', result);
callback();
});
},
(err) => {
if (err)
throw new Error(err);
else
console.log('All items updated');
});
Upvotes: 0
Reputation: 128
This should work
let arrData = [ { firstName: 'Mike', lastName: 'Jones' },
{ firstName: 'Joe', lastName: 'Smith' },
{ firstName: 'Bob', lastName: 'Johnson' } ];
function getMiddleName(arr){
arr.forEach(ar => {
//this will be your async request that gets the usrename
asynRequest.then(person => {
arr.MiddleName = person;
});
});
}
getMiddleName(arrData);`
Upvotes: 0
Reputation: 370639
Make an array of Promises, call Promise.all
on that array, and then insert the middle name to each:
const getMiddleNameProm = obj => new Promise((resolve) => {
GetMiddleName(obj, resolve);
});
Promise.all(arr.map(getMiddleNameProm))
.then((middleNames) => {
for (let i = 0; i < middleNames.length; i++) {
arr[i].MiddleName = middleNames[i];
}
// do stuff with populated arr here
});
});
Upvotes: 1