2016-09-28 82 views
0

對於我正在做的項目,我有一個基於文件及其內容構建樹模型的函數。我的解析文件函數是遞歸的,並且將繼續調用它的自我,直到它不能在目錄樹中更深入/擊中不包含更多文件的文件。但是我不知道如何設置這個函數的回調函數,因爲它是遞歸的。截至目前,我只是將構建樹方法超時,但這對我的問題是一個可怕的和不可靠的解決方案。這裏是我的代碼:Aysncronous遞歸方法中的回調?

function constructTree(dir){ 
    tree = new TreeModel() 
    root = tree.parse({name: 'Marshall McGee Sample Pack'}); 
    parseFiles(dir, root, tree); 
    setTimeout(function(){ 
    root.all().forEach(function(node){ 
     console.log(node.model.name); 
    }); 
    }, 1000) 
} 

function parseFiles(dir, parrent, tree){ 
    fs.readdir(dir, function(err, files){ 
    if(files){ 
     for(i = 0; i < files.length; i++){ 
      parrent.addChild(tree.parse({name: files[i]})); 
      console.log(files[i]); 
      parseFiles(dir + "/" + files[i], parrent, tree); 
     } 
    } 
    }); 
} 

此代碼「Works」,但可怕。我不知道如何確定我是否搜索了整個目錄或者如何正確執行此操作。我希望我解釋得很好!感謝和任何幫助appricated!

+0

你是什麼意思的回調函數? – prabodhprakash

+0

我添加了'javascript'標記,缺乏這個標記解釋了爲什麼直到現在你還沒有得到任何答案。 – trincot

回答

1

您應該爲您的parseFiles函數添加回調參數,並讓它在完成其作業(異步)時調用該回調函數。

爲了知道某個文件夾中的所有項目何時被遍歷,您應該保留一個計數,並且只有當最後一個已經完成時,通知調用者(通過他提供的回調),這部分樹完成(見count變量):

function constructTree(dir){ 
    var tree = new TreeModel() 
    var root = tree.parse({name: 'Marshall McGee Sample Pack'}); 
    // instead of timer, pass a callback function that should be called 
    // when the whole tree has been loaded. 
    parseFiles(dir, root, tree, function() { 
    root.all().forEach(function(node){ 
     console.log(node.model.name); 
    }); 
    }); 
} 

function parseFiles(dir, parrent, tree, done){ 
    fs.readdir(dir, function(err, files){ 
    // Only proceed here when there is at least one file (added condition) 
    if(files && files.length){ 
     // keep track how many items still need to be collected: 
     var count = files.length; 
     for(var i = 0; i < files.length; i++){ 
     parrent.addChild(tree.parse({name: files[i]})); 
     console.log(files[i]); 
     parseFiles(dir + "/" + files[i], parrent, tree, function() { 
      count--; 
      // if we have all items (recursively) added to the tree, notify the caller 
      if (!count && done) done(); 
     }); 
     } 
    } else { 
     // If no information in this folder, notify caller immediately 
     if (done) done(); 
    } 
    }); 
} 

由於主叫方沒有義務傳遞一個回調,代碼調用它之前檢查的done值。這就是爲什麼有if (done) done()

注意:與您的問題無關,但您應注意使用var關鍵字(或let,const)以避免不必要的全局變量創建。

+0

不客氣;-) – trincot

0

所做的每個函數調用都放在堆棧上。

Step 1: constructTree 
Step 2: calls parseFiles 
Step 3: calls parseFiles 
. 
. 
. 
Step n-1: calls parseFiles 
Step n: cannot parse any further 

在這一點上,它會開始回到

Step n-1 
Step n-2 
. 
. 
. 
Step 3 
Step 2 
Step 1 - and pointer returns to the original caller 

讓我知道,如果解決了這個問題,或者你有不同的關注。