2015-12-11 42 views
0

我对nodejs中的迭代函数有点麻烦。nodejs,mysql,异步迭代函数

我正在通过一个对象并检查该对象是否附有任何子对象(想想:一颗恒星有一个行星有一个月球有一个轨道站有一艘船)。

我想组装这一切到一个很好的对象阵列推送到客户端。

这里的功能:

 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; 
       } 

      }); 

     } 

当我触发函数返回的未定义一个节点列表。任何人都可以给我一个正确的方向指针吗?我无法得到它的工作

谢谢!

编辑:这里的数据样本,我itterating过:

的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 = ? 

样品节点列表输入:

[ { 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, 
} ] 

月球上有一个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

好了,该解决方案是相当明显的,有一次我把它弄出来。非常感谢@shennan让我走了。

的关键是:

  1. 为@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); 
    
            } 
    
           } 
    
          }); 
         } 
    
    1

    这是很难说是否有任何其他主要的问题,因为我看不到你喂养方法的数据。但是,这有一个主要问题:您正试图从使用异步方法调用的方法中输入return数据。

    异步方式是通过回调返回值。在你的代码,在你的榜样的最后function(回调)是从一个完全不同的范围中调用(从async框架内),使您的nodeListerr被在你不控制范围丢失。

    您需要重新考虑您的代码,以便将返回的数据传递给回调。您可以利用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 */ 
    
    }); 
    
    +0

    太棒了,谢谢。我确实在传输中看到(rslt = subNodeProc(rslt,sqlP,itteration_count);)你不传递回调。正确? – sn0r

    +1

    @ sn0r啊,我没有发现那个电话。这确实会使事情稍微复杂化,因为您正在调用相同的方法。你能否在你的问题中提供一些示例数据,以便我能更好地理解你的用例?我会在几个小时后回来。 – shennan

    +0

    感谢您的麻烦:)我添加了一些示例数据。 – sn0r