I'm trying to do some dynamic queries sequential but for any reason, the next code doesn't fulfil that desired behaviour.
var createEvent = function (user, notification) {
var action, query;
query = { agent: notification.agent, story: notification.story, type: notification.type };
action = { agent: notification.agent, story: notification.story, type: notification.type, ts: notification.ts };
return mongoose.model('Event').findOne(query).exec()
.then(function (response) {
if (response === null) {
return mongoose.model('Event').create(action)
.then(function (response) {
return mongoose.model('User').findByIdAndUpdate(user, { $push: { notifications: { _id: response._id }}});
});
}
return mongoose.model('User').findByIdAndUpdate(user, { $push: { notifications: { _id: notification._id }}}).exec();
});
setTimeout(resolve, 3000);
};
var moveNotifications = function (users) {
var promises = [];
users.map(function (user) {
if (user.notifications.length > 0) {
user.notifications.map(function (notification) {
promises.push(createEvent(user._id, notification));
});
}
});
Promise.each(promises, function (queue_item) {
return queue_item();
});
};
Could someone help me?
As you are calling createEvent
inside the nested Array#map
loops, you are starting all the queries at once - what you want to do is just get an array of id
and notification
to later pass to createEvent
in Promsise.each
Note: Not sure why you use Array#map
, as you never return anything from the map callback - you're basically doing Array#forEach
var moveNotifications = function(users) {
var items = [];
users.forEach(function(user) {
if (user.notifications.length > 0) {
user.notifications.forEach(function(notification) {
items.push({id: user._id, notification: notification});
});
}
});
return Promise.each(events, function(item) {
return createEvent(item._id, item.notification);
});
}
Alternatively, using Array#concat
to flatten a 2 level array that is returned by using (nested) Array#map
correctly you can achieve the same result
var moveNotifications = function(users) {
return Promise.each([].concat.apply([], users.map(function(user) {
return user.notifications.map(function(notification) {
return {id: user._id, notification: notification};
});
})), function(item) {
return createEvent(item._id, item.notification);
});
}
The above is easily made even more concise using the following ES2015 syntax:
=>
...
{a, b, c}
({a, b, c}) =>
var moveNotifications = users =>
Promise.each([].concat(...users.map(user =>
user.notifications.map(notification => ({id: user._id, notification}))
)), ({id, notification}) => createEvent(id, notification)
);
The extreme ES2016 one liner version :p
var moveNotifications = users => Promise.each([].concat(...users.map(user => user.notifications.map(notification => ({id: user._id, notification})))), ({id, notification}) => createEvent(id, notification));