nodejs,mysql,异步itterative函数

时间:2015-12-11 12:21:18

标签: javascript mysql node.js asynchronous

我在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
        },
        {...}]
    },
    {...}]
},
{...}]

2 个答案:

答案 0 :(得分: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 */

});

答案 1 :(得分:0)

好的,一旦我把它解决了,解决方案就非常明显了。非常感谢@shennan让我走了。

关键是:

  1. 正如@shennan所提​​到的那样,你不能使用回报,因为我们正在异步工作。这意味着回调
    1. 您必须为函数的每个部分触发回调。仅使用一个函数就不可能实现这一点,因此要获得返回的对象需要两个,每个都执行原始函数的不同部分。
    2. 这是我提出的问题。希望有人可以查看并给我一个意见......

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