以下功能以递归方式在文件夹中打印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 :(得分:26)
你的异步方法实例可能都在同时执行,你不知道预先有多少个。因此,您必须保持计数,然后在最后一个异步方法完成时使用回调。
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 :(得分: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();
}
});
}
这有点难看,但它应该有用。
答案 2 :(得分:0)
您可以将所有已完成的调用保存到变量中,并根据要处理的书签数量进行测试。到达结尾时(完成次数等于要处理的书签数量),然后执行最终功能。
这里有类似问题的答案,您可以使用代码作为指南:
How do I load a variable number of scripts with jQuery.getScript() before running javascript code?
答案 3 :(得分:0)
你可以做这样的事情JQFAQ.com。我正在更新以备将来使用。
答案 4 :(得分:-1)
可能是一个更好的方法,但你可以添加一个深度参数,如
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--;
});
});
}