将函数的执行同步为node.js中的回调参数

时间:2014-12-21 18:13:04

标签: javascript node.js asynchronous callback

我正在学习js(特别是节点和表达),目前正在努力理解究竟什么是同步和什么不是。

目前,我已经说过需要向B类服务发送请求的A型服务。 我想在一个公共函数中聚合这些请求,以便所有A类服务都可以使用它。

A型服务代码(直接在router.post中)

var post_data = <some data>
sendBServicePost(post_data,function (out_data) {
    var resp_data = JSON.parse(out_data);
    if (resp_data.status == "OK") {
      var msg = 'Request OK : '+out_data;
      console.log(msg);
      res.json({ status:"OK", message:msg});
    }
    else
    {
      var msg = 'Login KO: '+out_data;
      console.log(msg);
      res.json({ status:"KO_FUNC", message:msg});
    }
  }).on('error',function (e) {
    var msg = 'Error with call: ' + e.message;
    console.log(msg);
    res.json({ status:"KO_TECH", message:msg});
  });

这里是罪魁祸首的代码:

function sendBServicePost(post_data,callback) {
    var post_options = {
        // Some options
    };

    // Sending request
    var post_req = http.request(post_options, function(post_res) {
        post_res.on('data', function(out_data) {
          callback(out_data);
        });
    });
    post_req.write(post_data);
    post_req.end();
}

所以,发生的事情是我收到的错误是说我在发送响应时尝试添加响应标头,我认为这是因为A类服务的执行已经完成在达到回调函数代码之前 。 我认为回调是堆叠的,执行会经过完整的堆栈,所以我很难分辨这个链中究竟是什么异步。

有人可以就这件事情说清楚吗?我怎么能同步这个链?这里有一些最好的做法?

2 个答案:

答案 0 :(得分:0)

function sendBServicePost(post_data,callback) {
    var post_options = {
        // Some options
    };

    // << While this part is executing >>
    var post_req = http.request(post_options, function(post_res) {
        post_res.on('data', function(out_data) {
          // Anything you want to execute synchronously you can write here, before or after callback.
          callback(out_data);
        });
    });

    // << This part is also executing >>
    post_req.write(post_data);
    post_req.end();
}

答案 1 :(得分:0)

您现在看到的核心问题是,'data'事件可能会多次触发数据,因此您将多次调用callback,因此调用res.json多个时间,这会触发你的错误。

此外,node通常标准化了传递回调以使用第一个参数作为错误的代码,因此我建议如下:

function sendBServicePost(post_data, callback) {
    var post_options = {
        // Some options
    };

    // Sending request
    var post_req = http.request(post_options, function(post_res) {
        var pieces = [];
        post_res.on('data', function(out_data) {
            pieces.push(out_data);
        });
        post_res.on('end' function(){
            callback(null, Buffer.concat(pieces));
        });
        post_res.on('error', function(err){
            callback(err, null);
        });
    });
    post_req.on('error', function(err){
        callback(err, null);
    });

    post_req.write(post_data);
    post_req.end();
}

叫做:

var post_data = <some data>
sendBServicePost(post_data, function (err, out_data) {
    if (err){
        var msg = 'Error with call: ' + e.message;
        res.json({ status: "KO_TECH", message: msg});
        return;
    }

    var resp_data = JSON.parse(out_data);
    if (resp_data.status == "OK") {
        var msg = 'Request OK : ' + out_data;
        res.json({status: "OK", message: msg});
    } else {
        var msg = 'Login KO: ' + out_data;
        res.json({status: "KO_FUNC", message: msg});
    }
  });

如果你真的想要更像.on('error',的代码,那么你总是可以从sendBServicePost返回一个事件 - 发射器对象,但是我还建议你将你的回调重新设置为基于事件的,这样你就可以了不要混淆范式。