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

Synchronising the execution of a function as callback parameter in node.js

本文关键字:js 回调 node 参数 函数 执行 同步      更新时间:2023-09-26

我正在学习js(特别是node&express(,目前正在努力理解什么是同步,什么不是。

目前,我有需要向 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 类型服务的执行在到达回调函数代码之前已经完成.我认为回调是堆叠的,执行将经过整个堆栈,所以我很难说出这个链中到底什么是异步的。

有人可以对此事有所了解吗?如何同步此链?这里有一些最佳实践?

您现在看到的核心问题是'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返回一个事件发射器对象,但是我也建议将你的回调重新设计为基于事件的,这样你就不会混合范式。

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();
}