2015-12-11 44 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