Ошибка массива JavaScript Google Chrome? - PullRequest
0 голосов
/ 07 июля 2010

Я работаю над расширением Google Chrome.Во всплывающем окне у меня есть следующий код:

var bookmarks = [];
function appendBMTnode(node){
    bookmarks.push([node[0].title, node[0].id]);
}
function addchildren(results){
    for(x = 0; x < results.length; x++){
        bookmarks.push([results[x].title, results[x].id]);
        chrome.bookmarks.getChildren(results[x].id, addchildren);
    }
}
function getallbookmarks(){
    chrome.bookmarks.get('0', appendBMTnode);
    chrome.bookmarks.getChildren('0', addchildren);
}
getallbookmarks();
console.debug(bookmarks.length);
console.debug(bookmarks);

Теперь я бы предположил, что первая команда выдаст количество закладок, которые у меня есть.Действительно, когда я использую отладчик Chrome и добавляю bookmarks.length в список наблюдения, значение 418.В консоли отладчика я могу написать bookmarks.length, и он даст мне правильную длину.Я могу напечатать

for(x = 0; x < bookmarks.length; x++){ console.debug(bookmarks[x]); }

, и я получаю строковые представления каждого внутреннего массива.Тем не менее, этот оригинал console.debug(bookmarks.length) дает нулевой результат.И если я добавлю console.debug(bookmarks[0]); в popup.html, он скажет мне, что значение не определено.

Но если я добавлю следующее к getallbookmarks() (первый или последний):

for(x = 0; x < 10; x++){
    bookmarks.push(x);
}

затем bookmarks.length сначала будет 10, а затем 428. Также, когда я добавлю следующую функцию:

function printlen(){
    console.debug(bookmarks.length);
}

, а затем в теле, если я добавлю

<a href="#" onclick="printlen()">test</a>

тогда я также получу правильное значение bookmarks.length.

Любая подсказка, почему объекты закладок не будут регистрироваться?

1 Ответ

9 голосов
/ 07 июля 2010

chrome.bookmarks.get - асинхронная функция.Когда вы вызываете его, он сразу же возвращается, загружая данные закладки в фоновом режиме.

Так что, если вы посмотрите на bookmarks.length сразу после вызова на getallbookmarks(), оно, естественно, будет неполным.Когда вы позже нажмете кнопку printlen(), загрузка закладки завершится и массив будет заполнен.

Вы не можете знать, что ваш массив bookmarks заполнен и готов к использованию, покаоба appendBMTnode() и addchildren() были вызваны.Вот почему chrome.bookmark методы принимают функции обратного вызова, а не просто возвращают значение.

[править]:

как мне "ждать", пока все не загрузится?

На самом деле вы не можете, JavaScript не предоставляет инструментов языкового уровня (таких как потоки или сопрограммы) для синхронного выполнения асинхронного кода или наоборот.Вам придется привыкнуть к написанию асинхронного кода на основе функций обратного вызова.

В этом случае у вас может быть счетчик, который вы увеличиваете при каждом вызове get() или getChildren() и уменьшаете в концекаждого appendBMTnode и addchildren обратного вызова.Если в этот момент счетчик достигает нуля, асинхронные вызовы не ожидают, поэтому вы можете вызвать собственную функцию обратного вызова «завершение».Функции обратного вызова часто пишутся в виде выражений встроенных функций, чтобы сделать поток более понятным.

Проблема с кодом на данный момент состоит в том, что нет никакого внутреннего порядка для массива закладок, так как все вызывается параллельно.Если не гарантируется, что get() вернет результат раньше, чем getChildren(), и каждый раз, когда addchildren снова вызовет getChildren(), результаты для разных родителей могут появиться в любом порядке.

Рассмотрите возможность использованияметод getTree().Это даст вам полный список закладок за один раз, который, вероятно, будет значительно легче обрабатывать:

var bookmarks= [];
chrome.bookmarks.getTree(function(marks) {
    for (var i= 0; i<marks.length; i++)
        bookmarks.push([marks[i].title, marks[i].id]);
    // bookmarks is now populated. do code that relies on bookmarks here
});
// at this point bookmarks will still be empty, the callback function hasn't
// happened yet
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...