4

これはJavaで行うのは非常に簡単なタスクですが、javascriptの非同期性により、少なくとも今の私の知識では、このタスクは(私にとって)ほとんど不可能です(私はjavascriptをbashしようとはしていません。言語が大好きです!)。

それは非常に基本的です。トップレベルツリーには、私のmysqlデータベースにnullの親があります。子供を見つけるのは簡単です。子供たちは彼らに利用可能なラインを持っています。木の深さは可変です。

    private static Set<Tree> getBranches( Tree trunk ) {

    Set<Tree> treeSet = new HashSet<Tree>();

    if ( trunk != null ) {

        if ( trunk.hasLines() ) { //queries if tree has lines.  returns true or false
            treeSet.add( trunk );
        }

        for ( Tree tree : trunk.treeList ) {
            treeSet.addAll( getBranches( tree ) );
        }
    }

    return treeSet;
}

基本的に、このメソッドは、ツリーに使用可能な行があるかどうかをテストします。含まれている場合は、それらすべてをセットに追加します。そうでない場合は、行が見つかるまで続行します。

mysqlノードライブラリの非同期性により、このタスクは地獄に変わります。

これが私が今持っているものです

   function hasLines(tree_id, callback) {
        var ret;
        pool.query('SELECT * from pkg_line_tree where tree_id = ?', [tree_id], function (err, rows) {

            if (rows.length > 0) {
                ret = true;
            } else {
                ret = false;
            }
            callback(ret);
        });
    }


     function dig(tree_id, treeArray, callback) {

        pool.query('SELECT * from tree where parent_id = ?', [tree_id], function (err, rows) {

           if (rows) {

              for (var i in rows) {
                 hasLines(rows[i].tree_id, function (t) {

                    if (t) {
                       treeArray.push(rows[i].tree_id);
                    } else {
                       treeArray.concat(dig(rows[i].tree_id, treeArray));
                    }
                 });
              }

              if (callback) {
                 callback(treeArray);
              }

           }
        });

        return treeArray;
     }


     var treeArray = [];
     dig(52, treeArray, function (t) {
        res.json(t);
     });

私は本当にこのルートツリーで利用可能なすべての子を出力する必要があります。

これが意味をなさない場合はお知らせください。リファクタリングを試みます。ある種のポイントが伝わったことを願っています。私はこれを成し遂げるためにファイバーのようなものを使うのは嫌いですが、私は選択肢がありません。ありがとう。

4

2 に答える 2

2

非同期https://github.com/caolan/asyncを使用する必要があります

asyncのforEachメソッドを使用するようにdig関数を変更しました

function dig(tree_id, treeArray, AllDone) {
       pool.query('SELECT * from tree where parent_id = ?', [tree_id], function (err, rows) {
          if (rows) {
            async.forEach(
                rows,
                function(row, callback) {
                    hasLine(row.tree_id, function(t){
                        if (t) {
                            treeArray.push(row.tree_id);
                            callback();
                        }
                        else {
                            dig(row.tree_id, treeArray, callback);
                        }
                    });
                },
                function(err) {
                    if (err) AllDone(err, treeArray);
                    else AllDone(null, treeArray);
                });
            }
          else 
            AllDone(null, treeArray)
        });
}

treeArray = [];
dig(52, treeArray, function(err, t) {  
    res.json(t);  
});

行が配列であると仮定するforEachと、各行を調べてhasLineを実行すると、各反復はcallback終了時に関数を呼び出し、AllDoneすべてのcallback関数が呼び出されたときに呼び出されます。ここで注意が必要なのは再帰です。各再帰呼び出しにはforEachループがあり、AllDoneすべてcallbacksが終了したときにのみメソッドを呼び出します。

ただしforEach、並行して実行されるため、順序は保持されません

順序を気にしないのであれば、これでうまくいくと思います。

編集注文の問題を解決するために使用できます。forEachSeries

于 2012-09-04T22:43:06.077 に答える
2

現在、の使用にdig()は一貫性がありません。

// asynchronous with callback
dig(52, treeArray, function (t) {
   res.json(t);
});

// then synchronous with `return`?
treeArray.concat(dig(rows[i].tree_id, treeArray));

また、concat最後の行のは、呼び出された配列を変更しないため、実際にはあまり機能していません。のように新しいものを定義するのではなく、実際にdigパスとして使用したくない場合があります。したがって、そうすると、毎回それ自体の最後に追加されます。treeArraytreeSetgetBranchestreeArray

concat複数のsで使用することもできますがtreeSet、そのreturn値を保存する必要があります。

treeSet = treeSet.concat(subSet);

forまた、ループは続行する前に非同期操作を待機しないため、ループを非同期イテレータに置き換える必要があります。あなたがそれを試してみたいのであれば、asyncライブラリにはこれのためのいくつかのオプションがあります。

したがって、複数treeSetのs 、、、concatおよびを使用して、次のasync.forEachSeriesことを試すことができます。

function dig(tree_id, callback) {
  var treeSet = [];

  hasLines(tree_id, function (yep) {
    if (yep) {
      treeSet.push(tree_id);
    }

    pool.query('SELECT * from tree where parent_id = ?', [tree_id], function (err, rows) {

      function each(row, next) {
        dig(row.tree_id, function (subSet) {
          treeSet = treeSet.concat(subSet);
          next(null);
        });
      }

      function done() {
        callback(treeSet);
      }

      async.forEachSeries(rows, each, done);
    });
  });
}

dig(52, function (treeSet) {
  res.json(treeSet);
});
于 2012-09-04T23:16:35.963 に答える