簡體   English   中英

在node.js中將函數的執行同步為回調參數

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

我正在學習js(特別是node&express),目前正努力理解什么是同步,什么不是同步。

目前,我可以說A型服務需要將請求發送到B型服務。 我想將這些請求聚合到一個通用函數中,以便所有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型服務的執行已經完成。 我以為回調是堆疊的,執行將遍歷整個堆棧,因此,我很難說清此鏈中到底是什么異步。

有人可以闡明這件事嗎? 如何同步此鏈? 這里有一些最佳做法?

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

您現在看到的核心問題是'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返回一個事件發射器對象,但是我還建議您將回調修改為基於事件的,這樣您就不會混淆范式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM