I'm writing an extension for Chrome that basically plays around with the bookmarks. The following code is in the popup html file, and the bookmarkHelper() function is being called in the body onload event. It's supposed to check if a bookmark folder called "TestFolder" exists. If it exists, it removes all the bookmarks within the folder. If it doesn't, it creates the empty folder.
var rootFolder = undefined;
function bookmarkHelper() {
// Create TestFolder folder if it doesn't exist
chrome.bookmarks.getTree(function(tree) {
otherFolder = tree[0].children[1].children;
rootFolder = undefined;
for(i=0; i<otherFolder.length; i++) {
if(otherFolder[i].title == "TestFolder") {
rootFolder = otherFolder[i];
return;
}
}
chrome.bookmarks.create({'parentId': "2",
'title': 'TestFolder'},
function(newFolder) {} );
});
// Remove all bookmarks from the rootFolder
for (i=0; i<rootFolder.children.length; i++)
chrome.bookmarks.remove(rootFolder.children[i].id);
}
Now my problem is that when there's bookmarks in the folder, it doesn't remove them. But if I change the last 3 lines to
setTimeout(function(){
for (i=0; i<rootFolder.children.length; i++)
chrome.bookmarks.remove(rootFolder.children[i].id);
}, 100);
it deletes the bookmarks. In a separate case, when I inspect the popup, it deletes the bookmarks using the original code. This is very strange, and I didn't know quite what to make of it. Am I missing some anonymous-function-threading type concept here? Because AFAIK, JS is single-threaded.
Chrome API calls are asynchronous, so if you want to run them in order you need to put your code inside callbacks. Moreover your whole bookmarkHelper
should also be rewritten in asynchronous way, assuming you want to wait for a bookmark folder to be created before continue.
function bookmarkHelper(callback) {
// Create TestFolder folder if it doesn't exist
chrome.bookmarks.getTree(function(tree) {
otherFolder = tree[0].children[1].children;
rootFolder = undefined;
for(i=0; i<otherFolder.length; i++) {
if(otherFolder[i].title == "TestFolder") {
rootFolder = otherFolder[i];
//"return" here wouldn't return from bookmarkHelper as you probably expect
break;
}
}
//it would be easier to always just recreate TestFolder
if(rootFolder == undefined) {
chrome.bookmarks.create({'parentId': "2", 'title': 'TestFolder'}, callback);
} else {
// Remove whole rootFolder subtree
chrome.bookmarks.removeTree(rootFolder, function() {
chrome.bookmarks.create({'parentId': "2", 'title': 'TestFolder'}, callback);
});
}
});
}
//usage
bookmarkHelper(function(testFolder) {
//do something with testFolder
});
I remade it to always remove the whole tree and recreate it because otherwise you would need to monitor when the whole bunch of chrome.bookmarks.remove
callbacks is done executing in parallel in order to continue, which is nasty.