简体   繁体   English

如何处理Node中多个异步回调的结果

[英]How to handle results of multiple async callbacks in Node

I'm working on a scenario in Node which involves multiple async.map calls, one of which is nested in an _.map function as I need access to nested arrays. 我正在处理Node中涉及多个async.map调用的场景,其中一个嵌套在_.map函数中,因为我需要访问嵌套数组。 I'm struggling to properly combine the results of these calls into an array which I return in the end. 我正在努力将这些调用的结果正确组合到一个数组中,最后我将其返回。

More specifics on the scenario: 该方案的更多细节:

I start with a userId and query my games db to find all games which this userId is associated with. 我从一个userId开始,并查询我的游戏数据库以查找与此userId关联的所有games I pull gameId and description for each game. 我为每个游戏提取gameIddescription

I then query the gameId of each of these games to find all userId s associated with each game. 然后,我查询这些游戏中的每一个的gameId ,以查找与每个游戏相关联的所有userId I filter the original userId out of these results. 我从这些结果中过滤出了原始的userId

Next I query my users db for each of these userId s in order to get details such as user email and name . 接下来,我向我的用户数据库查询每个userId ,以获取详细信息,例如用户emailname (Note: this is where _.map comes into play as the userId s are nested in an array of arrays; each inner array representing a game). (注意:这是_.map发挥作用的地方,因为userId嵌套在一个数组数组中;每个内部数组代表一个游戏)。

The last step, and where I'm struggling, is how to combine these results and return them. 我正在努力的最后一步是如何组合这些结果并返回它们。 My final desired array looks like the below. 我最终想要的数组如下所示。 An array of game objects. 游戏对象数组。 Each game object has a gameId , description , and users property. 每个游戏对象都有一个gameIddescriptionusers属性。 users is an array of users associated with that game and has id , email , and name properties. users是与该游戏相关联的一组用户,并具有idemailname属性。

[
  {
    gameId: 'dfh48643hdgf',
    description: 'lorem ipsum...',
    users: [
      {
        id: 1,
        email: 'test@example.com',
        name: 'John Doe'
      },
      {
        id: 7,
        email: 'sample@example.com',
        name: 'Jane Smith'
      }, ...
    ]
  }, ...
]

Below is the code I currently have (Note: this code block is actually part of a larger async.series call): 以下是我当前拥有的代码(注意:此代码块实际上是较大的async.series调用的一部分):

sharedGames: function(next) {
  db.games.index({userId: userId},
    function(err, gamesData) {
      if (err) {
        logger.warn('Error retrieving games for userId %d', userId, err);
        next(err, null);
      } else {
        gamesData = _.map(gamesData, function(game) {
          return {
            gameId: game.id,
            description: game.description,
            users: []
          };
        });
        async.map(gamesdata,
          function(item, callback) {
            db.gameDetails.getGameUsers({gameId: item.gameId},
              function(err, users) {
                if (err) {
                  callback(err, null);
                } else {
                  callback(null, _.without(users.userIds, Number(userId)));
                }
              }
            );
          },
          function(err, results) {
            if (err) {
              next(null, null);
            } else {
              var flattenedResults = _.chain(results)
                .flatten()
                .uniq()
                .value();
              async.map(flattenedResults, function(user, callback) {
                db.users.getById(user, function(err, userDetails) {
                  if (err) {
                    callback(err, null);
                  } else {
                    callback(null, _.pick(userDetails, 'id', 'email', 'name'));
                  }
                });
              }, function(err, users) {
                if (err) {
                  next(null, null);
                } else {
                  _.each(results, function(result, index) {
                    _.each(result, function(user) {
                      var customerDetails = _.find(customers, function(u) {
                        return u.id === user;
                      });
                      gamesData[index].users.push(userDetails);
                    });
                  });
                  console.log(gamesData);
                  next(null, gamesdata);
                }
              });
            }
          }
        );
        next(null, []);
      }
    }
  );
}

So you can definitely accomplish what you're describing with async.auto . 因此,您绝对可以使用async.auto完成您要描述的async.auto Check this from their docs: 从他们的文档中检查:

async.auto({
get_data: function(callback){
    console.log('in get_data');
    // async code to get some data
    callback(null, 'data', 'converted to array');
},
make_folder: function(callback){
    console.log('in make_folder');
    // async code to create a directory to store a file in
    // this is run at the same time as getting the data
    callback(null, 'folder');
},
write_file: ['get_data', 'make_folder', function(callback, results){
    console.log('in write_file', JSON.stringify(results));
    // once there is some data and the directory exists,
    // write the data to a file in the directory
    callback(null, 'filename');
}],
email_link: ['write_file', function(callback, results){
    console.log('in email_link', JSON.stringify(results));
    // once the file is written let's email a link to it...
    // results.write_file contains the filename returned by write_file.
    callback(null, {'file':results.write_file, 'email':'user@example.com'});
}]
}, function(err, results) {
    console.log('err = ', err);
    console.log('results = ', results);
});

So if you follow the same approach, you can get the array of game objects by injecting more info every call. 因此,如果采用相同的方法,则可以通过在每次调用时注入更多信息来获得游戏对象数组。 You can also use async.waterfall . 您还可以使用async.waterfall Hope it helps 希望能帮助到你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM