猫鼬顺序承诺

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