最新消息: 电脑我帮您提供丰富的电脑知识,编程学习,软件下载,win7系统下载。

node.jsexpressmongoose在异步函数中组合异步函数循环

IT培训 admin 12浏览 0评论

node.js / express / mongoose在异步函数中组合异步函数循环

我正在使用Node.js和猫鼬来获取数据。在发送结果之前,我想遍历数据并获取另一个猫鼬集合的一些其他信息。

我不让它管理,第一个猫鼬呼叫等待,其他诺言完成。我认为我的诺言和.then调用的混合是一团糟...:S

我的代码:

exports.checkChats = (req, res, next) => {
console.log(req.userData.userId);
let modifiedChats = [];
let partner;
Messages.find({ $or: [{ "users.starter": req.userData.userId }, { "users.partner": req.userData.userId }] })
    .then(chats => {
        if (chats) {
            console.log('Start');
            const promises = chats.map(async chat => {
                if (chat.users.starter.toString() === req.userData.userId.toString()) {
                    console.log('fetch partnerData for partner ' + chat.users.partner);
                    partner = chat.users.partner;
                }
                if (chat.users.partner.toString() === req.userData.userId.toString()) {
                    console.log('fetch partnerData for starter ' + chat.users.starter);
                    partner = chat.users.starter;
                }
                User.findById(partner).then(fetchedPartner => {
                    console.log('Partner fetched: ', fetchedPartner.userName);
                    modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
                });
            });
            Promise.all(promises).then(() => {
                console.log('End');
                res.status(201).json({
                    message: 'Chats found',
                    chats: modifiedChats
                });
            });
        }
    }).catch(error => {
        res.status(500).json({
            message: 'Couldnt fetch chats!',
            error: error
        });
    });
};

和终端日志:

Start
fetch partnerData for partner 5eb8502aad51b72012a2ccd1
fetch partnerData for partner 5eb84c93ad51b72012a2cc56
End
Partner fetched:  Summer
Partner fetched:  Pepe

谢谢你们。

回答如下:

您的代码中的问题是这些代码段

const promises = chats.map(async chat => {
  if (chat.users.starter.toString() === req.userData.userId.toString()) {
    console.log('fetch partnerData for partner ' + chat.users.partner);
    partner = chat.users.partner;
  }
  if (chat.users.partner.toString() === req.userData.userId.toString()) {
    console.log('fetch partnerData for starter ' + chat.users.starter);
    partner = chat.users.starter;
  }
  User.findById(partner).then(fetchedPartner => {
    console.log('Partner fetched: ', fetchedPartner.userName);
    modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
  });
});

此循环的每次迭代都调用User.findById(partner),它返回一个Promise,并且是异步的。该函数并不知道它需要等待其结果。告诉函数等待User.findById(partner)完成的一种方法是添加return

return User.findById(partner).then(fetchedPartner => {
    console.log('Partner fetched: ', fetchedPartner.userName);
    modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
  });

您也可以删除异步输入

const promises = chats.map(async chat => {

没有用,因为仍然没有利用async/await


这里还是使用async/await重构代码的示例。

exports.checkChats = async (req, res, next) => { // by putting async here, you are enabling a function to use await
  try {
    console.log(req.userData.userId);
    let partner;
    const chats = await Messages.find({ $or: [{ "users.starter": req.userData.userId }, { "users.partner": req.userData.userId }] }); // by putting await before a function call the returns a promise, you will have the access to the value it will return by this syntax
    console.log('Start');
    const promises = chats.map(async chat => { // by putting async here, you are enabling a function to use await; This is also a function so you will need to put async here if you want to use await inside
      if (chat.users.starter.toString() === req.userData.userId.toString()) {
        console.log('fetch partnerData for partner ' + chat.users.partner);
        partner = chat.users.partner;
      }
      if (chat.users.partner.toString() === req.userData.userId.toString()) {
        console.log('fetch partnerData for starter ' + chat.users.starter);
        partner = chat.users.starter;
      }
      const fetchedPartner = await User.findById(partner); // same here, I put await because its a promise
      console.log('Partner fetched: ', fetchedPartner.userName);
      return { id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath }; // I am just returning the values here, by the end of the .map() it will have created an array of promises that each resolves these objects
    });
    const modifiedChats = await Promise.all(promises); // this will convert the array of promises to an array of the values that was resolve  by each of the promises.
    console.log('End');
    res.status(201).json({
      message: 'Chats found',
      chats: modifiedChats
    });
  } catch (error) { // using try catch the way of catching reject thrown errors / rejected promises
    res.status(500).json({
      message: 'Couldnt fetch chats!',
      error: error
    });
  }
};

node.js / express / mongoose在异步函数中组合异步函数循环

我正在使用Node.js和猫鼬来获取数据。在发送结果之前,我想遍历数据并获取另一个猫鼬集合的一些其他信息。

我不让它管理,第一个猫鼬呼叫等待,其他诺言完成。我认为我的诺言和.then调用的混合是一团糟...:S

我的代码:

exports.checkChats = (req, res, next) => {
console.log(req.userData.userId);
let modifiedChats = [];
let partner;
Messages.find({ $or: [{ "users.starter": req.userData.userId }, { "users.partner": req.userData.userId }] })
    .then(chats => {
        if (chats) {
            console.log('Start');
            const promises = chats.map(async chat => {
                if (chat.users.starter.toString() === req.userData.userId.toString()) {
                    console.log('fetch partnerData for partner ' + chat.users.partner);
                    partner = chat.users.partner;
                }
                if (chat.users.partner.toString() === req.userData.userId.toString()) {
                    console.log('fetch partnerData for starter ' + chat.users.starter);
                    partner = chat.users.starter;
                }
                User.findById(partner).then(fetchedPartner => {
                    console.log('Partner fetched: ', fetchedPartner.userName);
                    modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
                });
            });
            Promise.all(promises).then(() => {
                console.log('End');
                res.status(201).json({
                    message: 'Chats found',
                    chats: modifiedChats
                });
            });
        }
    }).catch(error => {
        res.status(500).json({
            message: 'Couldnt fetch chats!',
            error: error
        });
    });
};

和终端日志:

Start
fetch partnerData for partner 5eb8502aad51b72012a2ccd1
fetch partnerData for partner 5eb84c93ad51b72012a2cc56
End
Partner fetched:  Summer
Partner fetched:  Pepe

谢谢你们。

回答如下:

您的代码中的问题是这些代码段

const promises = chats.map(async chat => {
  if (chat.users.starter.toString() === req.userData.userId.toString()) {
    console.log('fetch partnerData for partner ' + chat.users.partner);
    partner = chat.users.partner;
  }
  if (chat.users.partner.toString() === req.userData.userId.toString()) {
    console.log('fetch partnerData for starter ' + chat.users.starter);
    partner = chat.users.starter;
  }
  User.findById(partner).then(fetchedPartner => {
    console.log('Partner fetched: ', fetchedPartner.userName);
    modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
  });
});

此循环的每次迭代都调用User.findById(partner),它返回一个Promise,并且是异步的。该函数并不知道它需要等待其结果。告诉函数等待User.findById(partner)完成的一种方法是添加return

return User.findById(partner).then(fetchedPartner => {
    console.log('Partner fetched: ', fetchedPartner.userName);
    modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
  });

您也可以删除异步输入

const promises = chats.map(async chat => {

没有用,因为仍然没有利用async/await


这里还是使用async/await重构代码的示例。

exports.checkChats = async (req, res, next) => { // by putting async here, you are enabling a function to use await
  try {
    console.log(req.userData.userId);
    let partner;
    const chats = await Messages.find({ $or: [{ "users.starter": req.userData.userId }, { "users.partner": req.userData.userId }] }); // by putting await before a function call the returns a promise, you will have the access to the value it will return by this syntax
    console.log('Start');
    const promises = chats.map(async chat => { // by putting async here, you are enabling a function to use await; This is also a function so you will need to put async here if you want to use await inside
      if (chat.users.starter.toString() === req.userData.userId.toString()) {
        console.log('fetch partnerData for partner ' + chat.users.partner);
        partner = chat.users.partner;
      }
      if (chat.users.partner.toString() === req.userData.userId.toString()) {
        console.log('fetch partnerData for starter ' + chat.users.starter);
        partner = chat.users.starter;
      }
      const fetchedPartner = await User.findById(partner); // same here, I put await because its a promise
      console.log('Partner fetched: ', fetchedPartner.userName);
      return { id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath }; // I am just returning the values here, by the end of the .map() it will have created an array of promises that each resolves these objects
    });
    const modifiedChats = await Promise.all(promises); // this will convert the array of promises to an array of the values that was resolve  by each of the promises.
    console.log('End');
    res.status(201).json({
      message: 'Chats found',
      chats: modifiedChats
    });
  } catch (error) { // using try catch the way of catching reject thrown errors / rejected promises
    res.status(500).json({
      message: 'Couldnt fetch chats!',
      error: error
    });
  }
};
发布评论

评论列表 (0)

  1. 暂无评论