我正在尝试顺序执行一些动态查询,但出于任何原因,下一个代码无法实现所需的行为。
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(); }); };有人能帮帮我吗?
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?
最满意答案
当您在嵌套的Array#map循环中调用createEvent ,您将立即启动所有查询 - 您要做的只是获取一个id和notification数组,以便稍后传递给Promsise.each中的Promsise.each
注意:不确定为什么使用Array#map ,因为你永远不会从map回调中返回任何内容 - 你基本上是在做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); }); }或者,使用Array#concat来展平通过正确使用(嵌套) Array#map返回的2级数组,可以获得相同的结果
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); }); }使用以下ES2015语法可以更加简洁地进行上述操作:
arrow functions => 传播运营商... 简写对象属性名{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) );
极端的ES2016单线版:p
var moveNotifications = users => Promise.each([].concat(...users.map(user => user.notifications.map(notification => ({id: user._id, notification})))), ({id, notification}) => createEvent(id, notification));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:
arrow functions => spread operator ... shorthand Object property names {a, b, c} Destructuring Assignment - Parameter Context Matching ({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));更多推荐
发布评论