Асинхронная функция подготовки JavaScript - PullRequest
0 голосов
/ 21 августа 2011

Чтобы ускорить мое приложение, я хочу подготовить некоторые данные до того, как DOM будет готов, а затем использовать эти данные, когда DOM будет готов.

Вот как это может быть:

var data = function prepareData(){
  ...
}();

$(document).ready(function() {

   // use data to build page

}

Какподготовить данные для последующего использования?Спасибо

1 Ответ

3 голосов
/ 21 августа 2011

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

var data = (function(){
    ...
})();

или используйте функцию объявление вместо:

var data = processData();
function processData() {
    ...
}

(Почему бы не использовать имя с выражением функции? Из-за ошибок в различных реализациях, особенно в Internet Explorer до IE9, из-за которого создаст две полностью не связанные функции.)

Однако мне не ясно, чего вы пытаетесь достичь. Когда браузер достигает элемента script, он переключается на интерпретатор JavaScript и ожидает его завершения, прежде чем продолжить сборку DOM (поскольку ваш сценарий может использовать document.write для добавления в поток токенов HTML). Вы можете использовать атрибуты async или defer , чтобы пообещать браузеру, что вы не собираетесь использовать document.write, в браузерах, которые их поддерживают, но ...


Обновление : ниже вы сказали:

потому что prepareData - это функция долгого времени, и я предположил, что браузер может выполнить это во время построения дерева DOM. К сожалению, '$ (document) .ready' срабатывает до того, как prepareData завершится. Вопрос в том, как научить $ (document) .ready ждать готовых данных.

Единственный способ, которым обработчик ready может вызвать триггер во время работы processData, - это если processData использует асинхронный ajax (или пару граничных условий вокруг alert, confirm и т.п., но Я полагаю, вы этого не делаете). И если бы это было так, вы не могли бы возвращать результат как возвращаемое значение из функции (хотя вы могли бы вернуть объект, который вы продолжали обновлять как результат обратных вызовов ajax). В противном случае это невозможно: JavaScript в браузерах является однопоточным, обработчик ready будет стоять в очереди, ожидая, пока интерпретатор завершит свою предыдущую задачу (processData).

Если processData не делает ничего асинхронного, я подозреваю, что любой наблюдаемый вами симптом заставляет вас думать, что обработчик ready запускает во время processData по другой причине.

Но в случае асинхронного ввода есть три варианта:

  1. Если вы не контролируете готовые обработчики, которые хотите задержать, вы можете взглянуть на функцию jQuery holdReady. Позвоните $.holdReady(true);, чтобы удержать событие, и используйте $.holdReady(false);, чтобы прекратить его удерживать.

  2. Достаточно просто перенести обработчик ready. Вот как я это сделаю (обратите внимание, что я все обернул в функцию определения объема, чтобы эти вещи не были глобальными):

    (function() {
        var data = processData();
    
        $(onPageReady);
    
        function processData() {
        }
    
        function onPageReady() {
            if (!data.ready) {
                // Wait for it to be ready
                setTimeout(onPageReady, 0); // 0 = As soon as possible, you may want a
                                            // longer delay depending on what `processData`
                                            // is waiting for
                return;
            }
        }
    
    })();
    

    Обратите внимание, что я с радостью использую data в функции onPageReady, потому что я знаю , что она есть; эта функция не будет работать до тех пор, пока не вернется processData. Но я предполагаю, что processData возвращает объект, который медленно заполняется с помощью ajax-вызовов, поэтому я использовал флаг ready для объекта, который будет установлен, когда все данные будут готовы.

  3. Если вы можете изменить processData, есть лучшее решение: processData активирует обработчик готовности, когда это будет сделано. Вот код, когда processData делается с тем, что ему нужно сделать:

    $(onPageReady);
    

    Это работает, потому что, если DOM еще не готов, он просто планирует вызов. Если DOM уже уже готов , jQuery немедленно вызовет вашу функцию. Это предотвращает грязный цикл выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...