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