使用异步时,MongoDB保持一致的顺序

时间:2018-07-10 08:01:53

标签: javascript node.js sockets

构建一个简单的聊天应用程序,我正在尝试获取用户消息,但是在尝试使用异步时,顺序根本不一致。

 const msgQuery = await Message.find({ chatId: id }).sort({
    createdAt: 1
  });
  if (msgQuery) {
    msgQuery.forEach(async message => {
      try {
        const postedById = message.postedById;
        const nameQuery = await User.findOne({ _id: postedById }).select({
          name: 1
        });

        console.log(nameQuery.name);

        if (nameQuery) {
          io.to(id).emit(
            'server message',
            postedById === message.userId ? nameQuery.name : 'Other',
            message.text,
            postedById === message.userId ? true : false
          );
        }
      } catch (e) {
        console.log(e);
      }
    });

message.text的结果始终为随机顺序。我尝试不使用nameQuery常量,但它可以正常工作,顺序是一致的,但是..我也需要解析名称。

1 个答案:

答案 0 :(得分:1)

您不能保证async函数将完成的顺序。不必在async函数内部发出,而是必须等待 all 所有异步函数完成,然后按顺序发出。我认为最简单的方法是将Promise.all.map一起使用。您也可以通过仅查询尚未找到的用户名来进行优化-将它们存储在一个对象或类似的对象中。

const messages = await Promise.all(msgQuery.map(async message => {
  /* query code */

  if (nameQuery) {
    return {
      postedByName,
      message: message.text,
      postedByUser,
    };
  }
}));

messages.filter(Boolean).forEach(({ postedByName, message, postedByUser }) => {
  io.to(id).emit(
    'server message',
    postedByName,
    message,
    postedByUser,
  });
});

messages数组将保留消息顺序,它将仅等待所有用户查询完成。