调用节点异步回调以完成操作

Node async callback being called for operations complete

我正在尝试使用异步库来处理异步函数,但无法获得我需要的功能。

基本思路是,我正在使用对 redis 数据库的多次调用构建一个 JSON 对象。在 redis 调用完成后,我只想 return JSON 对象,所以我尝试使用 async.parallel 但我似乎没有正确理解它。

我的回调是用空 JSON 对象调用的,然后可以看到函数中的控制台日志。

这是我的代码:

server.js:

getHostObject(redis,sess.hostName,function(data) {
  console.log('calledback data: '+JSON.stringify(data));
});

getHostObject.js

  var async = require('async');

  var getHostObject = function(redis, hostName, callback) {

    var hostObject = {
      hostName: hostName,
      pushers: [],
      tracklist: []
    };

    var getSongObject = function(err,song) {
      console.log('song got!');
      hostObject.tracklist.push(song);
    };

    var getSongs = function() {
      redis.lrange(hostName+":songs",0,-1, function(err,data) {
        if (err) {console.log('Error reading songs! '+hostName+'\n'+err);}
        for(var i=0;i<data.length;i++) {
          redis.hgetall(hostName+":song:"+data[i], getSongObject);
        }
      });
    };

    var getPusherObject = function(err,pusher) {
      console.log('pusher got!');
      hostObject.pushers.push(pusher);
    };

    var getPushers = function() {
      redis.smembers(hostName+":pushers", function(err, data) {
        if (err) {console.log('Error reading pushers! '+hostName+'\n'+err);}
        for(var i=0;i<data.length;i++) {
          redis.hgetall(hostName+":pusher:"+data[i], getPusherObject);
        }
      });
    };

    async.parallel([
      function() {
        getPushers();
      },
      function() {
        getSongs();
      }
    ],callback(hostObject));

  };


  module.exports = getHostObject;

控制台输出:

calledback data: {"hostName":"47B71","pushers":[],"tracklist":[]}
pusher got!
song got!

首先,在 getHostObject 函数内,在 async.parallel 调用中,您传递 callback(hostObject)。这将在执行异步代码之前进行评估,这就是为什么 hostObject 它是空的。

除此之外,async.parallel 需要知道您的个人任务何时完成。就是这样,您应该按照 error, result 约定调用任务回调。查看文档中的 the example

您需要更改 getPushersgetSongs 以使用这些回调,将结果传递给回调,最后在并行完整的 cb 中编写 hostObject

我试图根据您的代码在此处进行说明,您需要对其进行修改才能使其正常工作。

var getSongs = function(cb) {
      redis.lrange(hostName+":songs",0,-1, function(err,data) {
        if (err) {console.log('Error reading songs! '+hostName+'\n'+err);}
        for(var i=0;i<data.length;i++) {
          redis.hgetall(hostName+":song:"+data[i], getSongObject);
        }
        // tracklistData should be the tracklist array, you need to build it first.
        cb(null, tracklistData);
      });
    };

var getPushers = function(cb) {
      redis.smembers(hostName+":pushers", function(err, data) {
        if (err) {console.log('Error reading pushers! '+hostName+'\n'+err);}
        for(var i=0;i<data.length;i++) {
          redis.hgetall(hostName+":pusher:"+data[i], getPusherObject);
        }
        // pushersData should be the pushers array, you need to build it first
        cb(null, pushersData);
      });


     };

async.parallel(getSongs, getPushers, function(err, results){
   if(err) // err handling
   callback({
      hostName: hostName,
      pushers: results[1],
      tracklist: results[0]
    });
});

当我评论你需要先构建数组时,我的意思是看起来你可能希望在每个函数中使用 async.parallel 以及构建数组时。 也许像

var getPushers = function(cb) {
  redis.smembers(hostName+":pushers", function(err, data) {
    var getOperations = [];
    if (err) {console.log('Error reading pushers! '+hostName+'\n'+err);}

    for(var i=0;i<data.length;i++) {
      getOperations.push((function(pusher){
        return function(callback){
          redis.hgetall(hostName+":pusher:"+pusher, callback);
        }
      })(data[i]));
    }

    async.parallel(getOperations, function(err, pushers){
      cb(null, pushers);
    });

  });

 };