Вам нужно следует использовать скобки вокруг выражения функции для ясности (и потому что в аналогичной ситуации, когда вы определяете и вызываете функцию, но не используете возвращаемое значение, она будет синтаксическая ошибка без них). Кроме того, когда вы используете выражение функции, вы не хотите давать ему имя. Итак:
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
по другой причине.
Но в случае асинхронного ввода есть три варианта:
Если вы не контролируете готовые обработчики, которые хотите задержать, вы можете взглянуть на функцию jQuery holdReady
. Позвоните $.holdReady(true);
, чтобы удержать событие, и используйте $.holdReady(false);
, чтобы прекратить его удерживать.
Достаточно просто перенести обработчик 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
для объекта, который будет установлен, когда все данные будут готовы.
Если вы можете изменить processData
, есть лучшее решение: processData
активирует обработчик готовности, когда это будет сделано. Вот код, когда processData
делается с тем, что ему нужно сделать:
$(onPageReady);
Это работает, потому что, если DOM еще не готов, он просто планирует вызов. Если DOM уже уже готов , jQuery немедленно вызовет вашу функцию. Это предотвращает грязный цикл выше.