繁体   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