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

时间:2015-04-29 15:39:43

标签: javascript node.js asynchronous parallel-processing

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

基本思想是我使用对redis数据库的多次调用来构建JSON对象。我想在redis调用完成后才返回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!

1 个答案:

答案 0 :(得分:1)

首先,在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);
    });

  });

 };