我在nodejs中使用itterative函数时遇到了一些麻烦。
我正在踩过一个物体并检查该物体是否附有任何子物体(想想:一颗恒星有一颗行星有月球,轨道站有一艘船)。
我正在尝试将这一切组合成一个很好的对象数组,以推送到客户端。
这是功能:
var subNodeProc = function(nodeList,sqlP,itteration_count) {
var async = require('async');
--itteration_count;
async.each(nodeList,function(dd,cb){
var simple = {
sql:sqlP,
values:[dd.node_id],
timeout:40000
};
dd.subnodes = false;
connection.query(simple, function(err,rslt){
if (err) {
cb(err);
} else {
if (rslt.length > 0) {
var r = nodeList.indexOf(dd);
if (itteration_count > 0) {
rslt = subNodeProc(rslt,sqlP,itteration_count);
}
nodeList[r].subnodes = rslt;
}
cb();
}
});
},function(err){
if (err) {
return err;
} else {
return nodeList;
}
});
}
当我触发该函数时,它返回一个undefined的节点列表。任何人都可以给我指向正确的方向吗?我无法让它工作
谢谢!
编辑:这是我正在考虑的数据样本:
SQL语句:
SELECT n.id as node_id, n.name, n.system_id, n.parent_id as parent_id FROM nodes as n WHERE n.parent_id = ?
用于输入的示例nodeList:
[ { node_id: 1,
name: 'Planet A',
system_id: 1,
parent_id: null,
},
{ node_id: 2,
name: 'Moon',
system_id: 1,
parent_id: 1,
},
{ node_id: 3,
name: 'Debris',
system_id: 1,
parent_id: 2,
},
{ node_id: 4,
name: 'Asteroid',
system_id: 1,
parent_id: 1,
} ]
月球A的parent_id为1且node_id为2,月球A也有一艘船(船A,node_id:3,parent_id:2)围绕它运行。
我想要的是什么:
[ { node_id: 1,
name: 'Planet A',
system_id: 1,
parent_id: null,
subnodes:[{
node_id: 2,
name: 'Moon A',
system_id: 1,
parent_id: 1,
subnodes: [{
node_id:3,
name: 'Ship A',
system_id:1,
parent_id:2
},
{...}]
},
{...}]
},
{...}]
答案 0 :(得分:1)
很难判断是否存在任何其他重大问题,因为我无法看到您正在为该方法提供的数据。但是,这有一个主要问题:您正在尝试从使用异步方法调用的方法中获取return
数据。
异步方式是通过回调返回值。在您的代码中,示例中的最后一个function
(回调)是从完全不同的范围(async
框架内)调用的,因此nodeList
或err
在你无法控制的范围内迷失。
您需要重新考虑代码,以便将返回的数据传递给回调。您可以利用async
回调来实现此目的。为您的subNodeProc
方法添加回调参数。然后,您可以在async
完成后调用该回调,并将其传递给nodeList
:
var subNodeProc = function (nodeList, sqlP, itteration_count, cb) {
var async = require('async');
--itteration_count;
async.each(nodeList,function(dd, cb){
var simple = {
sql:sqlP,
values:[dd.node_id],
timeout:40000
};
dd.subnodes = false;
connection.query(simple, function(err, rslt){
if (err) {
cb(err);
} else {
if (rslt.length > 0) {
var r = nodeList.indexOf(dd);
if (itteration_count > 0) {
rslt = subNodeProc(rslt,sqlP,itteration_count);
}
nodeList[r].subnodes = rslt;
}
cb();
}
});
}, function (err) {
if (err)
throw err;
else
cb(nodeList);
});
}
然后你会使用这样的方法:
subNodeProc(nodeList, sqlP, itteration_count, function (processed) {
console.log(processed);
/* do whatever you want afterwards here */
});
答案 1 :(得分:0)
好的,一旦我把它解决了,解决方案就非常明显了。非常感谢@shennan让我走了。
关键是:
和
这是我提出的问题。希望有人可以查看并给我一个意见......
// Main processing function.
var subNodeProc = function(nodeList,sqlP,itteration_count,cback) {
var async = require('async');
itteration_count--;
async.each(nodeList,function(dd,cb){
if (itteration_count > 0) {
// Trigger SQL Walker subNodeProcWalker with the necessary data (dd.node_id in this case, with a callback)
subNodeProcWalker(dd.node_id,sqlP,itteration_count,function(nl) {
// Hey look! the walker has done its business. Time to fill the subnode and tell async we're done with this array node.
dd.subnodes = nl;
cb();
});
}
},function(){
// At the end of the run, return the nodelist intact.
cback(nodeList);
});
}
// SQL Walker with callback for subNodeProc
var subNodeProcWalker = function(node_id,sqlP,itteration_count,cback){
// assemble the object for the query and do the query
var simple = {
sql:sqlP,
values:[node_id],
timeout:40000
};
connection.query(simple, function(err,rslt){
if (err) {
console.log('Error in Query');
console.log(simple);
console.log(err);
cback(false);
} else {
// no error and a result? Quick! Trigger subNodeProc again
if (rslt.length > 0) {
subNodeProc(rslt,sqlP,itteration_count,function(nodePol) {
// Lookie lookie! A result from subNodeProc! There's life there! Quick! tell this function we're done!
cback(nodePol);
});
} else {
cback(false);
}
}
});
}