【问题标题】:mongoose sequential promises猫鼬顺序承诺
【发布时间】:2017-08-18 10:25:39
【问题描述】:

我正在尝试按顺序执行一些动态查询,但出于任何原因,下一个代码无法满足所需的行为。

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();
  });
};

有人可以帮我吗?

【问题讨论】:

  • 几件事...... setTimeout(resolve, 3000); 永远不会被执行,因为它在 return 之后 - 但那也一样,resolve 无论如何都没有定义。其次,您在 .map 回调中调用 createEvent - 所以所有这些 findOne 调用在第一个 .then 调用之前都是“飞行中”

标签: javascript mongoose promise bluebird


【解决方案1】:

当您在嵌套的 Array#map 循环中调用 createEvent 时,您将立即开始所有查询 - 您要做的只是获取 idnotification 的数组,然后传递给 @ 987654325@ in Promsise.each

注意:不知道你为什么使用Array#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 语法很容易使上述内容更加简洁:

  • 箭头函数=>
  • 扩展运算符...
  • 简写对象属性名称{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));

【讨论】:

  • 我不理解创建迭代承诺的概念!所以感谢您的回复,我发现它更加清晰!谢谢!
猜你喜欢
  • 2015-05-12
  • 1970-01-01
  • 2012-12-14
  • 2017-06-15
  • 2019-06-04
  • 2018-02-15
  • 2019-09-19
  • 2015-10-27
  • 2014-03-27
相关资源
最近更新 更多