Callback after end of asynchronous recursive function

18,514

Solution 1

Your asynchronous method instances may all be executing at once, and you don't know how many there will be beforehand. So, you'll have to keep count and then use a callback when the last asynchronous method is done.

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();
    });
}

Solution 2

I've recently had to solve this problem. The solution was similar to Eric's, but I found that I needed the count variable to be local to the function. Here's how I would solve this:

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();
    }
  });
}

It's a bit ugly, but it should work.

Share:
18,514

Related videos on Youtube

usertest
Author by

usertest

Updated on June 16, 2020

Comments

  • usertest
    usertest almost 4 years

    The function below prints Chrome bookmarks in a folder recursively. How could I alter the below function to call another function after the final recursive loop is processed? chrome.bookmarks.getChildren() is asynchronous which makes it difficult to know when the function is done processing everything.

    Thanks.

        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);
               });
            });
        }
    

    EDIT: Sorry, I don't think I was clear in the initial code example. I've updated the code to show the problem I'm having with the asynchronous function by calling the function multiple times. I'd like any code after the printBookmarks function calls to wait for all the printBookmarks functions to finish processing.

  • usertest
    usertest about 13 years
    Sorry, I don't think I was clear with my example code. Your code works for a single call to printBookmarks but i'd like to know when all call's to printBookmarks (made asynchronous) are done processing. I've updated my code. Thanks.
  • usertest
    usertest about 13 years
    I think the problem with that is, I don't know the number of bookmarks that'll be processed until they're actually processed.
  • nischayn22
    nischayn22 about 11 years
    and I thought I just invented this one :p
  • thispatchofsky
    thispatchofsky over 8 years
    Thank you for this solution. In my case, I had implicit detail in my returning data that indicated it was the final iteration, so I didn't use the count. But loved the callback concept. Thank you!