【问题标题】:nodejs, mysql, async itterative functionsnodejs,mysql,异步迭代函数
【发布时间】:2016-03-17 08:40:23
【问题描述】:

我在使用 nodejs 中的迭代函数时遇到了一些麻烦。

我正在逐步检查一个对象并检查该对象是否有任何附加的子对象(想想:一颗恒星有一颗行星有一个卫星有一个轨道站有一艘船)。

我正在尝试将这一切组装成一个很好的对象数组以推送给客户端。

函数如下:

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

            });

        }

当我触发该函数时,它会返回一个未定义的节点列表。谁能给我一个正确方向的指针?我无法让它工作

谢谢!

编辑:这是我正在迭代的数据示例:

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

月球 A 的 parent_id 为 1,node_id 为 2,月球 A 也有一艘船 (ship 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
        },
        {...}]
    },
    {...}]
},
{...}]

【问题讨论】:

    标签: javascript mysql node.js asynchronous


    【解决方案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 */
    
    });
    

    【讨论】:

    • 太棒了,谢谢。我确实看到在迭代中 (rslt = subNodeProc(rslt,sqlP,itteration_count);) 你没有传递回调。对吗?
    • @sn0r 啊,我没有发现那个电话。这确实使事情稍微复杂化,因为您正在调用相同的方法。您能否在问题中提供一些示例数据,以便我更好地理解您的用例?我会在几个小时后回到这个问题。
    • 感谢您的麻烦 :) 我添加了一些示例数据。
    • @sn0r 抱歉,我今天没有时间再看这个。不过,看起来您已经掌握了要点;根据经验,当方法变为异步时,它必须使用回调。因此,您之前在评论中指出的那句话是正确的。很高兴您成功地应用了逻辑。
    【解决方案2】:

    好的,解决方案很明显,一旦我弄清楚了。非常感谢@shennan 让我继续前进。

    关键是:

    1. 正如@shennan 提到的,您不使用退货,因为我们正在异步工作。这意味着回调

    1. 您必须为函数的每个部分触发回调。仅使用一个函数是不可能的,因此要让对象返回您需要两个,每个对象执行原始函数的不同部分。

    这是我想出的。希望有人能看一下,给我意见...

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      • 2021-07-14
      • 1970-01-01
      • 1970-01-01
      • 2016-07-10
      • 2018-09-05
      • 2021-06-08
      相关资源
      最近更新 更多