nodejs/javascript中的嵌套函数
据我所知,在javascript中嵌套函数会导致额外的声明/破坏,这可以通过使用“静态函数”甚至单例实现来避免。同样,“new”也做同样的事情,函数或对象的两个实例也是独立的副本 这是真的吗?如果是这样的话,我该怎么做才能拥有与嵌套函数和“new”相同的功能。这是一个服务器位于nodejs/javascript中的游戏。我已经达到了嵌套函数的8个级别,我开始担心了 例如:nodejs/javascript中的嵌套函数,javascript,node.js,Javascript,Node.js,据我所知,在javascript中嵌套函数会导致额外的声明/破坏,这可以通过使用“静态函数”甚至单例实现来避免。同样,“new”也做同样的事情,函数或对象的两个实例也是独立的副本 这是真的吗?如果是这样的话,我该怎么做才能拥有与嵌套函数和“new”相同的功能。这是一个服务器位于nodejs/javascript中的游戏。我已经达到了嵌套函数的8个级别,我开始担心了 例如: DB.cityUpdateUpkeep = function( cuid ) { /** @type {Array} */
DB.cityUpdateUpkeep = function( cuid )
{
/** @type {Array} */
var buildings = null;
DB.cityGet( cuid, function( error, city )
{
if( error )
{
console.log( "Couldn't get city" );
}
else
{
DB.iBuildings.find( {cuid:cuid}, function( error, cursor )
{
if( error )
{
console.log( "-error:" );
console.log( error );
}
else
{
cursor.toArray( function( error, response )
{
if( error )
{
console.log( "-error:" );
console.log( error );
}
else
{
console.log( "-the response:" );
console.log( response );
buildings = response;
var income = city.resources.income;
var storage = city.resources.storage;
var stored = city.resources.stored;
for( var buildingID in buildings )
{
var building = buildings[ buildingID ];
var blueprint = DB.bBuildings[ building.buid ];
if( blueprint.resources.income )
{
income = Utils.sumObjects( income, blueprint.resources.income );
}
if( blueprint.resources.storage )
{
storage = Utils.sumObjects( storage, blueprint.resources.storage );
}
if( blueprint.resources.stored )
{
stored = Utils.sumObjects( stored, blueprint.resources.stored );
}
}
console.log( "cuid: " + city._id + " income: " + income + " storage " + storage + " stored " + stored );
}
});
}
});
}
});
};
一种解决方案是存储函数,而不是匿名回调。它也更容易重用它们
DB.cityUpdateUpkeep = function (cuid) {
var findHandler = function () { ... };
DB.cityGet(cuid, function (error, city) {
...
DB.iBuildings.find({cuid:cuid}, findHandler);
...
});
};
我建议您选择一个控制流库(异步是最流行的一个),而不是一堆回调,您可以选择
瀑布式
async.parallel([
function(callback){
setTimeout(function(){
callback(null, 'one');
}, 200);
},
function(callback){
setTimeout(function(){
callback(null, 'two');
}, 100);
}
],
// optional callback
function(err, results){
// the results array will equal ['one','two'] even though
// the second function had a shorter timeout.
});
(代码借用自async的主网站)。因此,如果要在这些嵌套函数之间共享变量,可以在顶级的DB.cityUpdateUpkeep中定义它,其他嵌套函数也可以使用它。但是,请注意,如果您随时修改该变量,则稍后运行的函数将受到影响
这些嵌套函数有多糟糕?没什么,这是nodejs的本质(异步编程模型),你必须接受它。为了便于维护,您必须重新安排代码,不过请看一下平坦回调的方法(代码会更好一些)。对于您的特定示例,我更喜欢使用多种方法进行重构:
在出错时尽早返回方法(使您不必嵌套其他方法)
在异步调用不依赖时并发执行它们(注意DB.cityGet和DB.iBuildings.find-使代码运行得更快)
在嵌套外部创建函数和引用(例如checkComplete)
我的重构如下:
DB.cityUpdateUpkeep = function( cuid ){
/** @type {Array} */
var buildings = null;
var city = null;
var checkComplete = function(){
if (!city || !builings){
return;
}
var income = city.resources.income;
var storage = city.resources.storage;
var stored = city.resources.stored;
for( var buildingID in buildings ){
var building = buildings[ buildingID ];
var blueprint = DB.bBuildings[ building.buid ];
if( blueprint.resources.income ){
income = Utils.sumObjects( income, blueprint.resources.income );
}
if( blueprint.resources.storage ){
storage = Utils.sumObjects( storage, blueprint.resources.storage );
}
if( blueprint.resources.stored ){
stored = Utils.sumObjects( stored, blueprint.resources.stored );
}
}
console.log( "cuid: " + city._id + " income: " + income + " storage " + storage + " stored " + stored );
}
DB.cityGet(cuid, function(err, response){
if (err){
console.log("Couldn't get city");
return;
}
city = response;
checkComplete();
});
DB.iBuildings.find({cuid:cuid}, function(err, cursor){
if (err){
console.log(err);
return;
}
cursor.toArray(function(err, response){
if (err){
console.log(err)
return;
}
buildings = response;
checkComplete();
});
});
});
你是如何筑巢的?这些是什么功能?8级?认真地听起来像是回调而不是嵌套函数。你能举个例子吗?现在的问题太笼统了,可以通过向您介绍有关命名函数、使用承诺、使用事件等的文章来解决。。。注意我是如何从顶层到底层使用“城市”的。我将不得不对所有这些函数进行大量参数化,这可能会使事情变得过于复杂。只是考虑我在顶层添加一个参数,我需要在底部;我必须在整个链中传递该值:|不管怎样,这些嵌套函数到底有多糟糕?它确实看起来更好。每次调用cityUpdateUpkeep时,仍然会创建checkComplete和处理程序。不过,对于并行调用,+1。我很难弄清楚范围,但现在我明白了,我觉得它是多么的简单:)哎呀,关于检查完成,你是对的。只需将其移出函数即可。处理程序应该在现代javascript引擎中得到清理。事实上,据我所知,checkComplete也不会每次都重新分配-但最好是安全的。