2012-03-17 6 views
1

コールバックを使用する方法をゆっくりと学習しており、問題が発生しています。私は以下のコードは動作していないと思う。javascriptコールバックがデータを呼び出しの先頭にプッシュしない

私は、他の 'ツリー'エントリをヒットしたり、最後に何かを出力したりするときに、再帰関数に降下しないと言います。

私が遭遇した問題の1つは、forループのコールバックです。コールバックを呼び出す前にループの最後にいたかどうかを確認するためにカウンタを使用しただけです。

いくつかのガイダンスは本当に感謝しています。あなたはブロブデータtreeContentsを収集している変数が、それは新しい作成し、parseTree()を呼び出すたびに破壊されていますので、再帰関数のローカル変数であるため、

(function() { 
    'use strict'; 

    var objectsList = []; 

    function makeAJAXCall(hash, cb) { 
     $.ajaxSetup({ 
      accept: 'application/vnd.github.raw', 
      dataType: 'jsonp' 
     }); 

     $.ajax({ 
      url: hash, 
      success: function (json) { 

       if (cb) { 
        cb(json); 
       } 
      }, 
      error: function (error) { 
       console.error(error); 
       throw error; 
      } 
     }); 
    } 

    function parseBlob(hash, cb) { 
     makeAJAXCall(hash, function (returnedJSON) { // no loop as only one entry 
      if (cb) { 
       cb(returnedJSON.data); 
      } 
     }); 
    } 

    function complete(cb, loopLength, treeContents) { 
     concole.info(loopLength); 
     if (cb && loopLength === 0) { 
      objectsList.push(treeContents); 
      cb(); 
     } 
    } 

    function parseTree(hash, treeName, cb) { 
     var treeContents = {'tree': treeName, 'blobs': []}, loopLength, i, entry; 
     var tree = 'https://api.github.com/repos/myusername/SVG-Shapes/git/trees/' + hash; 
     makeAJAXCall(tree, function (returnedJSON) { 
      loopLength = returnedJSON.data.tree.length; 
      for (i = 0; i < returnedJSON.data.tree.length; i += 1) { 
       entry = returnedJSON.data.tree[i]; 
       if (entry.type === 'blob') { 
        if (entry.path.slice(-4) === '.svg') {  // we only want the svg images not the ignore file and README etc 
         parseBlob(entry.url, function (json) { 
          treeContents.blobs.push(json.content); 
          loopLength -= 1; 
          complete(hash, loopLength, cb); 
         }); 
        } 
       } else if (entry.type === 'tree') { 
        parseTree(entry.sha, entry.path, function() {console.info(objectsList);}); 
       } 
      } 
     }); 
    } 

    $(document).ready(function() { 
     parseTree('master', 'master', function() {  // master to start at the top and work our way down 
      console.info(objectsList); 
     }); 
    }); 
}()); 

答えて

3

あなたの再帰は正しく動作しません。データが蓄積されることはありません。この変数をparseTree()関数のスコープ外に作成する必要があります。そのため、この変数の1つのインスタンスが1回の呼び出しから次の呼び出しまで存続し、正しくデータを蓄積することができます。

この問題を解決するには、いくつかの方法があります。

  1. はあなたが関数の再帰的な部分は共通を共有する地元の関数であっても行うことができますparseTree()機能
  2. treeContentsの現在の状態を渡すことができますtreeContents変数。
  3. treeContents変数をグローバル変数にすることができます。

第二は、私の選択は、ここで、このようなものです:

function parseTree(topHash, topTreeName, topCb) { 
    var treeContents = {'tree': toptreeName, 'blobs': []}; 

    function parse(hash, treeName, cb) { 
     var loopLength, i, entry; 
     var tree = 'https://api.github.com/repos/myusername/SVG-Shapes/git/trees/' + hash; 
     makeAJAXCall(tree, function (returnedJSON) { 
      loopLength = returnedJSON.data.tree.length; 
      for (i = 0; i < returnedJSON.data.tree.length; i += 1) { 
       entry = returnedJSON.data.tree[i]; 
       if (entry.type === 'blob') { 
        if (entry.path.slice(-4) === '.svg') {  // we only want the svg images not the ignore file and README etc 
         parseBlob(entry.url, function (json) { 
          treeContents.blobs.push(json.content); 
          loopLength -= 1; 
          complete(hash, loopLength, cb); 
         }); 
        } 
       } else if (entry.type === 'tree') { 
        parse(entry.sha, entry.path, function() {console.info(objectsList);}); 
       } 
      } 
     }); 
    } 

    parse(topHash, topTreeName, topCb); 
} 

は、AJAX呼び出しが非同期であると仮定すると、あなたはまだあなたがすべての解析で行われているときに知っている方法を見つける必要がありますし、 treeContentsデータを渡す関数を呼び出す必要があります。そうでないと、そのデータは他の関数で使用できないためです。 ajax呼び出しの非同期性のために、単にparseTreeから戻すことはできません。

関連する問題