猫鼬顺序承诺
mongoose sequential promises
我正在尝试按顺序执行一些动态查询,但出于任何原因,下一个代码无法实现所需的行为。
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();
});
};
有人可以帮我吗?
当您在嵌套的 Array#map
循环中调用 createEvent
时,您将同时启动所有查询 - 您想要做的只是获取一个 id
的数组并且notification
稍后在 Promsise.each
中传递给 createEvent
注意:不确定你为什么使用 Array#map
,因为你从来没有 return 地图回调中的任何东西 - 你基本上是在做 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
来展平一个 2 级数组,该数组是 return 通过正确使用(嵌套)Array#map
编辑的,您可以获得相同的结果
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 语法可以轻松地使以上内容更加简洁:
- 箭头函数
=>
- 展开运算符
...
- shorthand 对象 属性 名称
{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 one liner版本:p
var moveNotifications = users => Promise.each([].concat(...users.map(user => user.notifications.map(notification => ({id: user._id, notification})))), ({id, notification}) => createEvent(id, notification));
我正在尝试按顺序执行一些动态查询,但出于任何原因,下一个代码无法实现所需的行为。
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();
});
};
有人可以帮我吗?
当您在嵌套的 Array#map
循环中调用 createEvent
时,您将同时启动所有查询 - 您想要做的只是获取一个 id
的数组并且notification
稍后在 Promsise.each
createEvent
注意:不确定你为什么使用 Array#map
,因为你从来没有 return 地图回调中的任何东西 - 你基本上是在做 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
来展平一个 2 级数组,该数组是 return 通过正确使用(嵌套)Array#map
编辑的,您可以获得相同的结果
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 语法可以轻松地使以上内容更加简洁:
- 箭头函数
=>
- 展开运算符
...
- shorthand 对象 属性 名称
{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 one liner版本:p
var moveNotifications = users => Promise.each([].concat(...users.map(user => user.notifications.map(notification => ({id: user._id, notification})))), ({id, notification}) => createEvent(id, notification));