Как определить, загружены ли файлы javascript?
Есть ли событие, которое запускается при загрузке файлов JavaScript? Проблема возникла из-за того, что YSlow рекомендует переместить файлы JavaScript в нижней части страницы. Это значит, что
$(document).ready(function1)
запускается перед загрузкой js файла, содержащего код для function1
.
Как избежать такой ситуации?
Ответы
Ответ 1
У меня нет ссылки на нее удобно, но теги script обрабатываются по порядку, и поэтому, если вы поместите свой $(document).ready(function1)
в тег script после тегов script, которые определяют функцию1, и т.д.., вам должно быть хорошо идти.
<script type='text/javascript' src='...'></script>
<script type='text/javascript' src='...'></script>
<script type='text/javascript'>
$(document).ready(function1);
</script>
Конечно, другой подход состоял бы в том, чтобы вы использовали только один тег script, в общем, путем объединения файлов как части процесса сборки. (Если вы не загружаете другие из CDN где-нибудь). Это также поможет улучшить воспринимаемую скорость вашей страницы.
EDIT: Только что понял, что я на самом деле не ответил на ваш вопрос: Я не думаю, что там было запущено кросс-браузерное событие, нет. Есть, если вы достаточно усердно работаете, см. ниже, Вы можете проверить символы и использовать setTimeout для перепланирования:
<script type='text/javascript'>
function fireWhenReady() {
if (typeof function1 != 'undefined') {
function1();
}
else {
setTimeout(fireWhenReady, 100);
}
}
$(document).ready(fireWhenReady);
</script>
... но вам не придется этого делать, если вы правильно настроили тэг script.
Обновление. Вы можете получать уведомления о загрузке для script
элементов, которые вы добавляете на страницу динамически, если хотите. Чтобы получить широкую поддержку браузера, вам нужно сделать две разные вещи, но в качестве комбинированного метода это работает:
function loadScript(path, callback) {
var done = false;
var scr = document.createElement('script');
scr.onload = handleLoad;
scr.onreadystatechange = handleReadyStateChange;
scr.onerror = handleError;
scr.src = path;
document.body.appendChild(scr);
function handleLoad() {
if (!done) {
done = true;
callback(path, "ok");
}
}
function handleReadyStateChange() {
var state;
if (!done) {
state = scr.readyState;
if (state === "complete") {
handleLoad();
}
}
}
function handleError() {
if (!done) {
done = true;
callback(path, "error");
}
}
}
По моему опыту, уведомление об ошибке (onerror
) не является 100% -ным кросс-браузером. Также обратите внимание, что некоторые браузеры будут выполнять оба механизма, следовательно, переменную done
, чтобы избежать дублирования уведомлений.
Ответ 2
Когда они говорят "внизу страницы", они буквально не означают нижнее: они означают перед закрывающим тегом </body>
. Поместите там свои скрипты, и они будут загружены перед событием DOMReady; поместите их позже, и DOM будет готов до их загрузки (потому что он завершается при анализе закрывающего тега </html>
), который, как вы нашли, не будет работать.
Если вам интересно, как я знаю, что это то, что они означают: я работал в Yahoo! и мы помещаем наши скрипты непосредственно перед тегом </body>
: -)
EDIT: также см. T.J. Crowder ответьте и убедитесь, что у вас есть вещи в правильном порядке.
Ответ 3
Взгляните на jQuery.load() http://api.jquery.com/load-event/
$('script').load(function () { });
Ответ 4
Я всегда звоню с конца файлов JavaScript для регистрации его загрузки, и он работал идеально для меня для всех браузеров.
Ex: У меня есть index.htm, Js1.js и Js2.js. Я добавляю функцию IAmReady (Id) в заголовок index.htm и вызываю ее с параметрами 1 и 2 с конца файлов, Js1 и Js2 соответственно. Функция IAmReady будет иметь логику для запуска загрузочного кода, когда он получит два вызова (сохраняя количество вызовов в статической/глобальной переменной) из двух js файлов.
Ответ 5
Далее к @T.J. Crowder answer, я добавил рекурсивный внешний цикл, который позволяет выполнять итерацию всех скриптов в массиве, а затем выполнять функцию после загрузки всех скриптов:
loadList([array of scripts], 0, function(){// do your post-scriptload stuff})
function loadList(list, i, callback)
{
{
loadScript(list[i], function()
{
if(i < list.length-1)
{
loadList(list, i+1, callback);
}
else
{
callback();
}
})
}
}
Конечно, вы можете сделать оболочку, чтобы избавиться от "0", если хотите:
function prettyLoadList(list, callback)
{
loadList(list, 0, callback);
}
Хорошая работа @T.J. Crowder - я прижимался к "просто добавлю задержку в пару секунд до запуска обратного вызова", который я видел в других потоках.
Ответ 6
Измените порядок загрузки ваших сценариев, чтобы function1
был определен перед использованием его в обратном вызове ready
.
Плюс, мне всегда было лучше определить обратный вызов ready
как анонимный метод, а затем его имя.
Ответ 7
Подобно T.J. написал: порядок определен (по крайней мере, он последователен, когда ваш браузер собирается выполнить какой-либо JavaScript, даже если он может каким-то образом загрузить скрипты). Однако, поскольку, по-видимому, у вас проблемы, возможно, вы используете сторонние библиотеки JavaScript, которые дают 404 Not Found или тайм-аут? Если это так, прочитайте Лучший способ использования jQuery в Google Googles, но вернитесь к моей размещенной библиотеке в Google.