异步递归函数结束后的回调

发布于 2024-10-18 09:59:55 字数 842 浏览 2 评论 0原文

下面的函数以递归方式打印文件夹中的 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 函数完成处理。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

靖瑶 2024-10-25 09:59:55

您的异步方法实例可能会同时执行,并且您事先不知道会有多少个。因此,您必须进行计数,然后在最后一个异步方法完成时使用回调。

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

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();
    });
}
风铃鹿 2024-10-25 09:59:55

我最近不得不解决这个问题。该解决方案与 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();
    }
  });
}

它有点难看,但应该可行。

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.

风追烟花雨 2024-10-25 09:59:55

您可以将所有已完成的调用保存到一个变量中,并根据要处理的书签数量进行测试。当您到达末尾时(完成的计数等于要处理的书签的数量),您将执行最终的函数。

此处有类似问题的答案,其中包含可用作指南的代码:

如何在运行 JavaScript 代码之前使用 jQuery.getScript() 加载可变数量的脚本?

You could save all your completed calls into a variable and test against the number of bookmarks you want to process. When you reach the end (the count of completions equals the amount of bookmarks to process), then you execute your final function.

An answer to a similar problem is here, with code that you can use as a guide:

How do I load a variable number of scripts with jQuery.getScript() before running javascript code?

丑丑阿 2024-10-25 09:59:55

你可以这样做 JQFAQ.com。我正在更新以供将来使用。

you can do something like this JQFAQ.com.I'm updating for the future uses.

梦断已成空 2024-10-25 09:59:55

可能是一个更好的方法来解决这个问题,但您可以添加一个深度参数,例如

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

Might be a better way to go about this, but you could add a depth parameter, something like

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

EDIT in response to comment

This is a variation on another answer for a slightly different approach.

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--;
        });
    });
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文