如何使用nodejs同步此过程?

时间:2013-05-11 07:30:48

标签: node.js

我需要迭代一个数组,对于我通过调用HTTP call来应用操作的每个项目。

难点在于我需要syncronize这个过程以便在循环之后调用回调(在HTTP call执行所有操作之后包含数组)。

让我们考虑一下这个简短的例子:

 function customName(name, callback) {
   var option = {
        host:'changename.com',
        path: '/'+name,
        headers: { 'Content-Type': 'application/json'  },
        port: 80,
        method:'POST'
    };

    var req = http.request(option, function(res) {
        var output = "";
        res.on('data', function (chunk) {
            output += chunk;
        });

        res.on('end', function() {
            var obj = JSON.parse(output);
            callback(obj.res);
        });
    });

    req.on('error', function(e) {
        console.error(e.message);
    });

    req.end();
}

function changeNames(OldNames, callback) {
  var Res = [];
  for (name in OldNames) {
    customName(OldNames[name], function(new_name) { Res.push(new_name); });
  });
  callback(Res);
}

var Names = ['toto', 'tata', 'titi'];
changeNames(Names, function(Names) {
    //...
});

此处循环在第一个HTTP call之前结束,因此Res array为空。

我们如何同步此执行?

我知道在nodejs中同步治疗并不是很好。你认为与客户端逐个传递名称而不构建数组更好吗?

1 个答案:

答案 0 :(得分:2)

您可以使用async.map。你传递了你的名字列表,它会为每个名字运行getOriginalName函数(我认为你错误地称之为customName)并收集结果,最后它将调用一个函数一系列结果:

var http  = require('http');
var async = require('async');

function getOriginalName(name, callback) {
  var option = {
    host:'changename.com',
    path: '/'+name,
    headers: { 'Content-Type': 'application/json'  },
    port: 80,
    method:'POST'
  };

  var req = http.request(option, function(res) {
    var output = "";
    res.on('data', function (chunk) {
      output += chunk;
    });

    res.on('end', function() {
      var obj = JSON.parse(output);
      callback(null, obj.res);
    });
  });

  req.on('error', function(e) {
    callback(e);
  });

  req.end();
}

function changeNames(OldNames, callback) {
  async.map(OldNames, getOriginalName, callback);
}

var Names = ['toto', 'tata', 'titi'];
changeNames(Names, function(err, NewNames) {
  console.log('N', NewNames);
});