javascript 异步递归函数结束后的回调
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5048861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Callback after end of asynchronous recursive function
提问by usertest
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.
下面的函数递归地打印文件夹中的 Chrome 书签。在处理最终递归循环后,如何更改以下函数以调用另一个函数?chrome.bookmarks.getChildren()是异步的,这使得很难知道函数何时完成处理所有内容。
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 printBookmarksfunction calls to wait for all the printBookmarksfunctions to finish processing.
编辑:对不起,我认为我在最初的代码示例中没有说清楚。我已经更新了代码,通过多次调用该函数来显示我在使用异步函数时遇到的问题。我希望printBookmarks函数调用后的任何代码等待所有printBookmarks函数完成处理。
回答by Eric Mickelsen
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();
});
}
回答by Jimmy Z
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:
我最近不得不解决这个问题。该解决方案类似于 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();
}
});
}
It's a bit ugly, but it should work.
这有点难看,但它应该可以工作。
回答by Karthi Keyan
回答by Matt King
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?
回答by dfb
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--;
});
});
}

