2011-02-19 86 views
16

下面的函数以递归方式在文件夹中打印Chrome书签。在最后的递归循环被处理后,我怎么能改变下面的函数来调用另一个函数呢? chrome.bookmarks.getChildren()是异步的,这使得很难知道函数何时处理完所有事情。异步递归函数结束后回调

谢谢。

for (var i = 0; i < foldersArray.length; i++) { 
     // The loop makes several calls with different folder IDs. 
     printBookmarks(foldersArray[i]); 
    } 

    // I'd like any code here to be run only after the above has 
    //finished processing  

    function printBookmarks(id) { 
     chrome.bookmarks.getChildren(id, function(children) { 
      children.forEach(function(bookmark) { 
       console.debug(bookmark.title); 
       printBookmarks(bookmark.id); 
      }); 
     }); 
    } 

编辑:对不起,我不认为我是在初始代码示例中清楚。我更新了代码,通过多次调用该函数来显示我在异步函数中遇到的问题。我想要printBookmarks函数调用后的任何代码等待所有printBookmarks函数完成处理。

回答

0

可能是一个更好的方式去,但你可以在响应添加的深度参数,像

printBookmarks('0', 0); 

function printBookmarks(id, depth) { 
    chrome.bookmarks.getChildren(id, function(children) { 
     children.forEach(function(bookmark) { 
      console.debug(bookmark.title); 
      printBookmarks(bookmark.id, depth + 1); 
     }); 
     if(depth == 0) yourFunction(); 
    });  
} 

编辑评论

这是另一种答案的变化一个稍微不同的方法。

runCount = 0; 
for (var i = 0; i < foldersArray.length; i++) { 
    // The loop makes several calls with different folder IDs. 
    printBookmarks(foldersArray[i]); 
    runCount++; 
} 

while(runCount > 0) { // sleep for 10ms or whatnot} 
// I'd like any code here to be run only after the above has 
// finished processing.  

function printBookmarks(id) { 
    chrome.bookmarks.getChildren(id, function(children) { 
     children.forEach(function(bookmark) { 
      console.debug(bookmark.title); 
      printBookmarks(bookmark.id); 
      runCount--; 
     }); 
    }); 
} 
+0

对不起,我不认为我清楚我的示例代码。您的代码适用于打印书签的单个调用,但是我想知道何时所有调用printBookmarks(异步)都已完成处理。我更新了我的代码。谢谢。 – usertest 2011-02-19 06:26:11

25

您的异步方法实例可能都是一次执行的,并且您不知道预先有多少个。所以,你必须保持计数,然后在最后一个异步方法完成时使用回调。

for (var i = 0; i < foldersArray.length; i++) { 
    // The loop makes several calls with different folder IDs. 
    printBookmarks(foldersArray[i], thingsToDoAfter); 
} 

function thingsToDoAfter() { 
    // I'd like any code here to be run only after the above has 
    // finished processing. 
} 

var count = 0; 

function printBookmarks(id, callback) { 
    count++; 
    chrome.bookmarks.getChildren(id, function(children) { 
     children.forEach(function(bookmark) { 
      console.debug(bookmark.title); 
      printBookmarks(bookmark.id, callback); 
     }); 
     count--; 
     if (count === 0 && callback) 
      callback(); 
    }); 
} 
+1

,我想我只是发明了这个:p – nischayn22 2013-04-19 19:22:46

+0

谢谢你的解决方案。就我而言,我在返回的数据中隐含了细节,表明这是最后一次迭代,所以我没有使用count。但喜欢回调概念。谢谢! – 2015-12-11 18:16:39

2

我最近不得不解决这个问题。该解决方案与Eric的相似,但是我发现我需要count变量作为函数的本地变量。这是我将如何解决这个问题:

for(var i=0;i<foldersArray.length; i++){ 
    // The loop make's several call's with different folder ID's. 
    var printed_children = 0; 
    printBookmarks(foldersArray[i],function() { 
    printed_children++; 
    if(printed_children == foldersArray.length){ 
     // You know you are done! 
    } 
    }); 
} 
// I'd like any code here to be run only after the above has 
//finished processing. 


function printBookmarks(id,finished_callback) { 
    // the printed_children count is local so that it can keep track of 
    // whether or not this level of recursion is complete and should call 
    // back to the previous level 
    var printed_children = 0; 
    chrome.bookmarks.getChildren(id, function(children) { 
    children.forEach(function(bookmark) { 
     console.debug(bookmark.title); 
     // added a callback function to the printBookmarks so that it can 
     // check to see if all upstream recursions have completed. 
     printBookmarks(bookmark.id,function() { 
     printed_children++; 
     if(printed_children == children.length){ 
      finished_callback(); 
     } 
     }); 
    }); 
    if(children.length == 0){ 
     finished_callback(); 
    } 
    }); 
} 

这有点难看,但它应该工作。

0

你可以做这样的事情JQFAQ.com。我正在更新以备将来使用。