【问题标题】:Waiting for asynchronous task to complete nodejs等待异步任务完成nodejs
【发布时间】:2023-08-01 03:58:01
【问题描述】:

我正在创建一个应用程序,其中用户可以有很多房间,每个房间可以有很多频道,这是我检索房间和相应频道时的代码:

getRooms: function (req, res) {
            User.find({id: req.cookies.claver_id}).exec(function (err, result) {
               if (err) {
                  return res.send(400);
               }
               rooms = result[0].rooms;
               if (rooms.length === 1) {//No room defaults to ['']
                   return res.send(400);
               }

               var roomsObj = {};
               var roomsArr = [];//we will place the roomsObj inside the roomsArr

               var chansObj = {};
               var chansArr = [];

               async.each(rooms, function (roomId, cb){
                    roomsObj = {};
                   if (roomId !== '') {
                    Rooms.findOne({id: roomId}).exec(function (err, room){
                        roomName = room.name; 
                        inviteLink = room.inviteLink;
                        roomsObj.name = roomName;
                        roomsObj.id = roomId;
                        roomsObj.inviteLink = inviteLink;

                        var channels = room.channels;
                        async.each(channels, function (channelId, cb) {
                             chansObj = {};
                            Channels.findOne({id: channelId}).exec(function (err, channel){
                            chansObj.name = channel.channelName;
                            chansObj.id = channelId;
                            chansObj.type = channel.channelType;
                            chansArr.push(chansObj);
                            cb();
                       });
                        }, 
                        function (err) {

                        });


                    }); 
                }
                cb(); 

               }, function (err) {
                   roomsObj.channels = chansArr;
                    roomsArr.push(roomsObj);
                   sails.log(roomsArr);

               }); 



            });
        }

假设返回一个具有以下结构的javascript对象:

[ { name: "Room Name",
    roomId: "Room Id",
    inviteLink: "Room Invite Link",
    channels: [
                {
                 name: "Channel Name",
                 id: "channel Id"
                 }
               ]
   }

]

但我总是得到一个空数组,因为async.each(rooms, function (roomId, cb){ }) 不等待async.each(channels, function (channelId, cb) {}) 完成,所以我有空房间对象。请问这个问题怎么解决?

【问题讨论】:

  • 明确你想要达到的目标。如我所见,您想要“获取用户的所有房间并更新分配给房间的每个频道”,对吗?
  • 听起来像是 Promises 的案例。
  • @zabaware 是的,这正是我想要实现的目标。
  • 为什么要在应用代码中迭代房间 n 个频道?为什么不使用 SQL 连接(假设你使用 sequelize.js)

标签: node.js asynchronous sails.js sails-mongo


【解决方案1】:

您应该在完成channels 循环后调用您的rooms's callback 循环。

你应该这样做:

getRooms: function (req, res) {
            User.find({id: req.cookies.claver_id}).exec(function (err, result) {
               if (err) {
                  return res.send(400);
               }
               rooms = result[0].rooms;
               if (rooms.length === 1) {//No room defaults to ['']
                   return res.send(400);
               }

               var roomsObj = {};
               var roomsArr = [];//we will place the roomsObj inside the roomsArr

               var chansObj = {};
               var chansArr = [];

               async.each(rooms, function (roomId, callback1){
                    roomsObj = {};
                   if (roomId !== '') {
                    Rooms.findOne({id: roomId}).exec(function (err, room){
                        roomName = room.name; 
                        inviteLink = room.inviteLink;
                        roomsObj.name = roomName;
                        roomsObj.id = roomId;
                        roomsObj.inviteLink = inviteLink;

                        var channels = room.channels;
                        var i=0;
                        async.each(channels, function (channelId, callback2) {
                             chansObj = {};
                            Channels.findOne({id: channelId}).exec(function (err, channel){
                            chansObj.name = channel.channelName;
                            chansObj.id = channelId;
                            chansObj.type = channel.channelType;
                            chansArr.push(chansObj);
                            i++;
                            if(i===(channels.length-1)){
                              i=0;
                               callback1(); 
                            }else{
                            callback2();
                            }
                       });
                        }, 
                        function (err) {
                        });
                    }); 
                }

               }, function (err) {
                   roomsObj.channels = chansArr;
                    roomsArr.push(roomsObj);
                   sails.log(roomsArr);
               }); 
            });
        }

【讨论】:

  • 我尝试了您的解决方案,但它返回错误“回调已调用”
  • 不幸的是,我仍然遇到同样的错误 - 回调已被调用
  • 我不认为它失败了,你检查我更新的答案了吗?因为这两个条件永远不会同时调用
【解决方案2】:

我解决了,确实是promise的情况,我使用bluebird promise结合异步-修改后的代码:

getRooms: function (req, res) {
            User.find({id: req.cookies.claver_id}).exec(function (err, result) {
               if (err) {
                  return res.send(400);
               }
               rooms = result[0].rooms;
               if (rooms.length === 1) {//No room defaults to ['']
                   return res.send(400);
               }

                var roomsObj = {};
                var roomsArr = [];//we will place the roomsObj inside the roomsArr

                var chansObj = {};
                var chansArr = [];
               Promise.each(rooms, function (roomId, callback1){
                    roomsObj = {};
                   if (roomId !== '') {
                    async.series ([
                      function () {
                          Rooms.findOne({id: roomId}).then(function (room){
                        roomName = room.name; 
                        inviteLink = room.inviteLink;
                        roomsObj.name = roomName;
                        roomsObj.id = roomId;
                        roomsObj.inviteLink = inviteLink;
                         channels = room.channels;
                         sails.log(roomName);
                         })
                     }
                     ]);
                      return   Promise.each(channels, function (channelId) {
                           return Promise.all([
                             Channels.findOne({id: channelId}).then(function (channel){
                            chansObj = {};
                            chansObj.name = channel.channelName;
                            chansObj.id = channelId;
                            chansObj.type = channel.channelType;
                            chansArr.push(chansObj);
                            sails.log(chansObj);
                          })
                           ]).then(function () {
                               sails.log('done one');

                           });
                        }).then(function () {
                             roomsObj.channels = chansArr; 
                             roomsArr.push(roomsObj);
                            sails.log('done all');
                            chansArr = [];

                        });
              }
               }).then(function () {
                        sails.log(roomsArr);
                        sails.log("grand finish");
                    });

            });
        }

感谢所有做出贡献的人。

【讨论】: