【发布时间】:2017-04-26 22:00:22
【问题描述】:
我有以下功能。抱歉,它有点长……但实际上并没有太多内容。 这是一个简单的函数,将循环传递消息,并通过 websockets 发送它们。
最关键的部分,也是这个问题的症结,是:这条线会导致堆栈填满吗?
// through this loop
sendMessagesInTab( tabId, cb );
...?基本上,当循环结束时,可能已将更多记录添加到列表中。由于这个函数只会运行一次(那里有一个信号量,currentlyDeliveringTab[ tabId ]),所以当它完成时,我想再次检查列表中没有添加任何内容。为此,我使用了函数本身。
根据我的测试,我实际上并没有设法填满堆栈。我认为那是因为这不是“递归”,因为一切都是异步的。但我很困惑:如果所有时间都添加,这会耗尽所有可用内存吗?
function sendMessagesInTab( tabId, cb ){
consolelog("Entered sendMessagesInTab for tab", tabId);
// Semaphore. Only one instance of this is to run at any given time
if( currentlyDeliveringTab[ tabId ] ){
consolelog("Already running for tab ", tabId);
return;
}
currentlyDeliveringTab[ tabId ] = true;
consolelog("Looking up tab...");
stores.tabs.dbLayer.selectById( tabId, function( err, tab ){
if( err ){
delete currentlyDeliveringTab[ tabId ];
return cb( err );
}
if( ! tab ){
delete currentlyDeliveringTab[ tabId ];
return new Error("tabId not found!");
}
stores.tabMessages.dbLayer.selectByHash( { tabId: tabId }, function( err, tabMessages ){
if( err ){
delete currentlyDeliveringTab[ tabId ];
return cb( err );
}
if( !tabMessages.length ){
consolelog("No messages to be delivered, that's it...");
delete currentlyDeliveringTab[ tabId ];
return cb( null );
}
/*
// TESTING RECURSION
delete currentlyDeliveringTab[ tabId ];
return sendMessagesInTab( tabId, function(err ) { console.log("ERROR:", err ) } );
*/
consolelog("There are messages to be delivered:", tabId, tabMessages.length );
async.eachSeries(
tabMessages,
function( record, cb ){
consolelog("Checking the connection...");
// If the connection is not there, all good but "false" (delivery failed)
var ws = connections[ record.tabId ] && connections[ record.tabId ].ws;
if( ! ws ) return cb( new Error("No websocket connection") ); // End of cycle will kill currentlyDeliveringTab
var message = record.message;
message.messageId = record.id;
// Attempt delivery over websocket. If it works, great. If it doesn't,
// sorry.
consolelog("Attempt to stringify the message", tabId);
try {
var strMessage = JSON.stringify( message );
} catch ( err ){
return cb( err );
}
consolelog("Sending message through the websocket", tabId);
ws.send( strMessage, function( err ){
if( err ) return cb( err ); // End of cycle will kill currentlyDeliveringTab
consolelog("Deleting the message", tabId);
stores.tabMessages.dbLayer.deleteById( record.id, function( err ){
if( err ) return cb( err ); // End of cycle will kill currentlyDeliveringTab
consolelog("Updating lastSync", tabId);
cb( null );
});
})
},
function( err ){
if( err ){
consolelog("ERROR!", err );
delete currentlyDeliveringTab[ tabId ];
return cb( err );
}
consolelog("All messages have been sent successfully!");
consolelog("Now running sendMessagesInTab again in case messages were added WHILE sending these");
delete currentlyDeliveringTab[ tabId ];
// Rerun sendMessagesInTab to check that messages weren't added while going
// through this loop
sendMessagesInTab( tabId, cb );
}
);
});
});
}
【问题讨论】:
标签: node.js asynchronous recursion