[英]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.