I am using loadash map function to do some structuring of data. The data returns a set of ids for which i need to query the db and add the result to the map and then return but the data is returned later and my function returns first. How to make the return of map wait and then return in function.
let result = _.chain(value)
.groupBy('pubId')
.pairs()
.map(function(currentItem) {
let item = _.object(_.zip(['ID', 'targetting'], currentItem));
propsToBeDeleted.forEach(function(prop) {
item.targetting.forEach(d => {
item.publishername = d.RTB.name;
item.type = d.type;
delete d[prop];
});
});
item.targetting.map(d => {
if (d.type == 15) {
d.name = Object.keys(JSON.parse(d.value));
d.value = Object.values(JSON.parse(d.value))[0];
item.dspIds = [];
}
if (d.type == 16) {
let value = JSON.parse(d.value);
d.name = Object.keys(JSON.parse(d.value)).filter(d => d != 'profileId');
d.value = value;
item.dspIds = d.value.profileId;
dspAccount.find({where: {id: 139}}, (err, data) => {
// async call wait here to get data and attach to item
item.x = data ;
});
delete d.value.profileId;
d.value = JSON.stringify(d.value);
}
});
return item;
})
.value();
I also tried using promises
promises.push(new Promise((resolve, reject) => {
if (data.id) {
XX.upsertWithWhere({id: data.id}, payload, (err, data) => {
if (err) {
return reject(err);
}
return resolve(data);
});
}
}));
});
Promise.all(promises).then((data) => {
callback(null, data);
}, err => {
callback(err);
});
Update i have already listed the promise .all method that doesnot work . So it cannot be called duplicate
Things are slightly tricky because you have an outer .map()
and an inner .map()
, containing an asynchronous element.
The asynchronous element effectively makes the whole thing asynchronous, requiring that :
.map()
is aggregated with Promise.all(), and the aggregate Promise returned to the outer .map()
. .map()
is aggregated with Promise.all(). .then()
. First, to make the main code block simpler and easier to read, create a promisified version of dspAccount.findAsync()
.
dspAccount.findAsync = function(query) {
return new Promise(function(resolve, reject) {
dspAccount.find(query, (err, data) => {
if(err) {
reject(err);
} else {
resolve(data);
}
});
});
}
Then the main code block can be written as follows :
let outerPromises = _.chain(value)
.groupBy('pubId')
.pairs()
.map(function(currentItem) {
let item = _.object(_.zip(['ID', 'targetting'], currentItem));
item.targetting.forEach(d => {
item.publishername = d.RTB.name;
item.type = d.type;
propsToBeDeleted.forEach(function(prop) {
delete d[prop];
});
});
let innerPromises = item.targetting.map(d => {
let value = JSON.parse(d.value);
if (d.type == 15) { // synchronous - `innerPromises` receives a null
item.dspIds = []; //
d.name = Object.keys(value);
d.value = Object.values(value)[0];
return null;
}
if (d.type == 16) { // asynchronous - `innerPromises` receives a Promise
return dspAccount.findAsync({where: {id: 139}})
.then(data => {
d.name = Object.keys(value).filter(d => d != 'profileId');
item.dspIds = value.profileId;
delete value.profileId;
item.x = data;
d.value = JSON.stringify(value);
});
}
});
return Promise.all(innerPromises).then(() => item); // aggregate inner promises and return
})
.value(); // returns the outerPromises array
Promise.all(outerPromises) // aggregate outer promises
.then(items => {
// do stuff with items here
})
.catch(error => {
// something went wrong
// log/display error
// take remedial action as required
});
I expect there's still some work to do. It doesn't look right that item
should be mutated in the item.targetting.map()
loop. The last element of item.targetting
to deliver its result (synch or asynch) will determine the composition of item
. That may not be what you want. If it is what you want, then more control will need to be exercised to ensure that the last result delivered is the result arising from the final element of item.targetting
.
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.