簡體   English   中英

閉包和異步node.js函數

[英]Closures & async node.js functions

所有,

試圖繞過node.js上下文中的閉包(異步調用)。

我有以下代碼:

timer = setInterval(pollOID, 1000);

function pollOID() {
    for (channel in channels) {
        session.get({ oid: channels[channel].oid }, function (varbinds) {
               console.log("The " + channels[channel].name + " is " + varbinds);
        });
    }
}

該代碼使用setInterval回調中的循環每秒輪詢路由器以獲取SNMP數據,以查詢路由器中的多個SNMP實體。 session.get函數具有異步回調,以處理來自路由器的結果。

SNMP位工作正常,我的問題是關於如何在會話異步回調中保留循環變量通道的值。

我得到以下結果:

The Download Attenuation is 7.5
The Download Attenuation is 361600
The Download Attenuation is 60

因此,對於每次對session.get的調用,循環變量通道都會更改,因為該函數正在從路由器返回正確的值。 我的問題是,channels [channel] .name使用的是channel的當前值,到回調返回循環時,該當前值已經結束,且channel為2(第三個循環,即名稱字符串“下載衰減”)。 因此,我需要將session.get回調內部的channel值保持為調用回調時的值,以便在session.get回調中使用正確的channel [channel] .name。

我知道我必須為此使用閉包,但是嘗試了多種不同的方法后,我無法使其正常工作。 有什么線索可以指示我正確的方向嗎? 謝謝!

您可以創建一個簡單的閉包以保留channel的本地副本。

 function pollOID() {
    for (channel in channels) {
      (function(channel){
        session.get({ oid: channels[channel].oid }, function (varbinds) {
               console.log("The " + channels[channel].name + " is " + varbinds);
        });
     })(channel);
  }

或者,您也可以使用bind傳入參數,但是上下文將在回調內部改變。

for (channel in channels) {
    session.get({ oid: channels[channel].oid }, (function (channel, varbinds) {
           console.log("The " + channels[channel].name + " is " + varbinds);
    }).bind(this, channel));
}

就像您猜到的那樣,問題是由於在回調函數中訪問channel是一個共享變量,並且在調用回調函數時,您的for循環已經運行完畢,並且channel會保留從channels枚舉的最后一個key

另一種方法是使用異步模塊 ,這可以簡化控制流程,從而可以在引入更多異步調用時提高可讀性。

function pollOID() {
    for (channel in channels) {
        (function(channel){
        session.get({ oid: channels[channel].oid }, function (varbinds) {
           console.log("The " + channels[channel].name + " is " + varbinds);
        });
    })(channel);
}

變成

function pollOID() {
    var log = function(channel, cb){
        session.get({ oid: channel.oid }, function (varbinds) {
           console.log("The " + channel.name + " is " + varbinds);
           cb(); // Moves onto next element in channels when cb is called
        });
    };
    var allDone = function(err, result) {
        // all tasks are complete
    };
    async.each(channels, log, allDone);
}

async.each將並行運行,因此如果需要按順序運行,請改用async.eachSeries

暫無
暫無

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

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