Паралельная загрузка скрипта javascript и выполнение по onDomReady.

Содержание

Паралельная загрузка скрипта javascript и выполнение по onDomReady.

Группа: Главные администраторы
Сообщений: 14349
Регистрация: 12.10.2007
Из: Twilight Zone
Пользователь №: 1

Известно, что следуя идеям старой школы, а именно, добавляя ссылки на JS и CSS в страницы, может обернуться большим временем загрузки страницы. Браузер отображает страницу по мере скачивания, но останавливается, если натыкается на тег script со ссылкой, до того момента, пока скрипт не будет загружен и выполнен. Сайты стали использовать всё большее количество скриптов, начальное отображение страницы занимает всё больше времени, к примеру, на этой странице, которую вы читаете, 13 скриптов, 7 из которых находятся в head’е. Ко всему прочему, некоторые браузеры по-прежнему придерживаются ограничений на одновременное количество загрузок с одного хоста.

Сразу предлагаю принять, что все JS файлы минимизированы, и передаются в сжатом виде.

Существует несколько решений, как то:

— поместить стили и скрипты прямо в страницу;

— установка аттрибутов async/defer тегу script;

— склеить все скрипты в один файл;

— помесить ссылки на скрипты в конец body;

— разместить все файлы на CDN/на разных хостах;

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

Существует интересная техника, которая решает проблему паузы перед начальным отображением страницы, а заодно добавляет некоторые удобства. Рискну предположить, что техника эта многим знакома, но тем не менее здесь я о ней упоминаний не видел.

Началось всё, конечно, с того, что я взялся за один проект, и в какой-то момент мне показалось, что простенькая страница достаточно долго загружается, и посмотрел на график загрузки, и на результаты YSlow. Огонь на секунду потух в моих глазах, но зная, что может быть лучше, я полез искать,

Разберём недостатки перечисленных выше методик.

Помещение скриптов и стилей прямо в страницу

Очевидно, что это решение подходит только для маленьких страниц, где не много скриптов стилей, так как в случае перезагрузки страницы будут повторно загружаться статические данные, и кеширование не может сработать. Решение вполне оправдано для небольших скриптов и стилей, жизненно необходимых с того самого момента, как страница загружена.

Установка аттрибутов async/defer тегу script

Аттрибуты async и defer тега script поддерживается следующими бразуерами, что может показаться недостаточным для тех, кто делает сайты, на которые могут заходить люди с устаревшими браузерами, а также Opera, что особенно актуально в рунете.

Из недостатков также можно отметить, что скрипты, загруженные из тега с аттрибутом defer, не могут использовать document.write, так как их исполнение не синохронизировано с парсером страницы.

Склеивание скриптов и стилей

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

Помещение stylesheet в head, а script — в конец body

Достойно упоминания и использования, но в этом случае, как и в описанных выше, до момента document.ready могут быть неразрешённые зависимости между скриптами, и если для jQuery с плагинами это допустимо, то для варианта, когда мы загружаем библиотеку API Facebook’а или VKontakte, и хотим тут же запустить наш скрипт, который пошёт на API запрос определения, залогинен ли пользователь, это сулит костылями, либо загрузкой библиотеки API в начале страницы, блокируя её отображение, что отягощается необходимостью вызова DNS resolve.

Использование CDN может снизить загрузку на собственный сервер, но может и увеличить и уменьшить время загрузки, а может и полностью блокировать загрузку скрипта, как в случае атаки на CDN сервер или блокировки CDN сервера на провайдере или в сети предприятия.

Какие ещё есть решения?

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

Где-то в заметках у меня нашёлся HeadJS, но с тех пор, как я впервые на него наткнулся, он серьёзно заматерел, и научился делать не только то, что нам нужно, но и многое другое. Несмотря на то, что библиотека явно хороша, а в минифицированном виде занимает всего 3КБ, я решил поискать альтернатив и нашёл аж 14 аналогичных библиотек, краткое и не всегда верное сравнение которых можно найти в этой заметке, плюс load.js и include.js. Бегло пробежавшись по представленным библиотекам и отметя сначала большие (>3КБ), а потом те, которые не понравились мне по синтаксису или принципу работы, я лично для себя выбрал YepNope.js, входящий в состав Modernizr. Авторы библиотеки сообщают, что библиотека не лучше и не хуже остальных, и выполняет ту же задачу, что и остальные, и что они сами в разных проектах используют также и другие загрузчики.

Итак, что же и как делает загрузчик ресурсов на примере YepNope:

Исполнение загруженных скриптов идёт в указанном порядке.

Далее в блоке инициализации:

yepnope( <
load: [‘//connect.facebook.net/ru_RU/all.js’, ‘/javascripts/facebook_auth_callback.js’],
complete: function() <
FB.init()
FB.Event.subscribe(‘auth.statusChange’, facebook_auth)
>
>)

Итак, мы получаем все желаемые плюшки, как то параллельная загрузка, определённость времени выполнения скрипта, зависиммости, обратные вызовы по готовности.

Пример загрузки стилей:

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

Авторы скриптов не могут прийти к единому принципу работы и интерфейсу API, и продолжают создавать всё новые загрузч ики. В связи с этим автор HeadJS предлагает встроить поддержку порядка загрузки в спецификации, и автор $script.js его в этом поддерживает, но пока это пройдёт через спецификации и будет работать одинаково во всех браузерах, нам предстоит пользоваться загрузчиками.

Каков же итоговый рецепт?

— встроить в head страницы script, указывающий на загрузчик;

— встроить inline скрипт, использующий загрузчик для подгрузки других скриптов и стилей;

— объединять скрипты и стили, использующиеся только совместно, в один для минимизации количества HTTP запросов;

— минимизировать скрипты и стили;

— убедиться в том, что сервер пакует передаваемые данные gzip’ом;

— убедиться в том, что сервер правильно кеширует;

— осторожно и вдумчиво использовать сторонние CDN и дополнительные хосты.

При написании топика делал оглядку на следующие материалы, рекоммендуемые к прочтению:

Простая загрузка скрипта при помощи yepnope.js

yepnope.js — это специальный инструмент, созданный Алексом Секстоном и Ральфом Холцманом в конце февраля 2011, который позволяет совершать асинхронную подгрузку как JavaScript, так и CSS файлов. В этом уроке мы рассмотрим, как пользоваться данным инструментом, и постараемся определить новые возможности, которые перед нами открываются.

Илон Маск рекомендует:  Что такое код ifx_blobinfile_mode

Этот прекрасный подгрузчик ресурсов занимает всего лишь 1.6KB и, с недавних пор, тесно связан с очень популярным на сегодняшний день инструментом Modernizer. Yepnope предназначен для загрузки полифилов, предварительно созданного кэша и других интернет ресурсов в асинхронном режиме!

Для тех, кто не знаком с понятием полифил, могу сказать, что данный объект является своего рода плагином или подпрограммой, которая позволяет воспользоваться новыми и современными технологиями вне зависимости от браузера, который установлен на клиенте. Я говорю о веб sql базах данных, CSS3 переходах и т.д.

На данный момент, Yepnope также поддерживает множество префиксов и фильтров, которые при взаимодействии с url ресурсом, предназначены для более детальной настройки основной функциональности программы. Помимо всех приведённых достоинств, yepnope также предоставляет вам механизм, предназначенный для определения ваших собственных фильтров. Теперь давайте взглянем на то, что можно сделать при помощи yepnope.js!

Асинхронная загрузка скриптов

Прежде, чем мы полностью внедримся в yepnope и множество его особенностей, вам очень важно понять сам процесс асинхронной подгрузки. Также важно знать, почему этот метод так популярен на сегодняшний день, и какими преимуществами он обладает по сравнению с обычной загрузкой файла.

Асинхронные загрузки устраняют проблему блокирования исходного файла со скриптом.

Как правило, JavaScript файлы, загруженные через тег

Javascript параллельной загрузки

Я слышал, что JavaScripts файлы на веб-страницах не были загружены параллельно, так что я сделал некоторые эксперимент по светлячок с помощью поджигатели. Тем не менее, я видел JavaScripts были закаченными параллельно, и веб-страница включена sripts в пожилом фьюжн образом:

Так как статья, которую я прочитал была написана в 2009 году, мне интересно, если что-то изменилось после того, или же светлячок сделал JavaScripts погрузочного по-другому ??

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

Таким образом, в то время как браузер может загружать тег сценария параллельно, она ждет, пока он не сможет выполнить их в последовательности (при условии, что они являются нормальными тегами рядного сценария без каких-либо специальных атрибутов, таких как «отложить» или «асинхр»). Но даже в тех случаях (webworkers, не то, что здесь обсуждается, за исключением), JavaScript однопоточен так только один кусок JavaScript будет выполняться одновременно.

Это не о загрузке , а о разборе и выполнении . Если второй файл Javascript зависит от некоторой глобальной переменной , заданной в первом Javascript файл, то он не может быть выполнена и даже не полностью разобран до загрузки первой один. Поскольку не существует простой способ для браузера действительно определить, имеется ли такая зависимость, безопасный способ для разбора и выполнения файлов последовательно.

Поскольку существует возможность делать document.write() команды и вообще изменить DOM, в то время как Javscript обрабатывается и выполняется, разбор и рендеринг HTML должен ждать, тоже.

Есть хаки , такие как это , что будет динамически добавить новое определение сценария, который загружается и разобранным параллельно. Более элегантный это атрибут Defer , но браузеры все не справиться с этим то же самое.

Обычно сценарии не загружаются параллельно, так как иногда загрузки заказа важно.

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

Тем не менее, есть способы, чтобы разрешить загрузку скриптов параллельно:

Как примечание стороны, есть некоторые общие атрибуты разработчики , как правило , использовать с

Асинхронная и отложенная загрузка JavaScript на сайте

Приветствую, друзья! Знаете ли Вы, что загрузка JavaScript является одним из самых узких мест в производительности сайта? Сегодня моя основная задача — объяснить что такое асинхронная загрузка скрипта и каким образом она влияет на быстродействие и производительность сайта.

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

  • конфигурации хостинга,
  • скорости интернет-соединения,
  • размера файла и других…

По этой причине анализатор скорости загрузки сайта Google PageSpeed Insights рекомендует удалить из верхней части страницы код JavaScript, блокирующий ее отображение. Хорошей практикой является размещение скриптов в нижней части сайта, например, перед закрывающим тегом

Асинхронная загрузка JavaScript — ускоряем загрузку страниц

Современные веб-страницы сильно перегружены файлами javascript. Это ведет к замедлению загрузки и последующего отображения страницы. В худших условиях посетителю сайта приходится ждать до 30 секунд.

Ускоряем загрузку html страниц

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

HTML устроен так, что веб-страница загружается, синхронно (строка за строкой) загружая по очереди все включенные в html-код элементы.

Таким образом, загрузка тормозится в местах с javascript строками.

Выход есть: поместить явавские строки в конец html документа (следовательно их загрузка будет происходить после прорисовки всей страницы) и только после этого содержимое блоков будет отображено в нужных местах. Это называется асинхронная загрузка JavaScript.

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

Есть несколько подходов. Начну по порядку.

Загрузка javascript файла осуществляется так:

Стандарт HTML5 поддерживает возможность асинхронной загрузки скриптов, что может значительно ускорить общее время получения страницы. Просто добавьте async или defer.

Чем же отличаются атрибуты async и defer

В обоих случаях мы получаем асинхронную загрузку скриптов. Разница заключается только в моменте, когда скрипт начинает выполнятся. Скрипт с атрибутом async выполнится при первой же возможности после его полной загрузки, но до загрузки объекта window. В случае использования атрибута defer — скрипт не нарушит порядок своего выполнения по отношению к остальным скриптам и его выполнение произойдет после полной загрузки и парсинга страницы, но до события DOMContentLoaded объекта document.

К сожалению, этот механизм на сегодняшний день не работает во всех браузерах (особенно это касается IE). Также не будет работать, если в файле script.js есть строки document.write.

Как известно всем мастерам, Google уделяет особое внимание скорости загрузки сайтов, и понижает медленные в поисковой выдаче. Что бы помочь, Гугл разработал специальный скрипт, при помощи которого можно сделать асинхронную загрузку javascript.

Чтобы использовать, просто заменяем

В самых старых версиях IE (6 и ниже) асинхронная загрузка к сожалению не работает, но таких пользователей уже практически нет. Все остальные браузеры и сервисы успешно пользуются современной ускоренной загрузкой web-страниц.

Рекомендую самый быстрый VPS на немецких серверах за разумные деньги — FastVPS

Уроки JavaScript – выполнение кода после полной загрузки DOM

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

Всякий раз, когда вы используете JavaScript для манипулирования вашей страницей, вам нужно дождаться события готовности документа. Событие готовности документа сигнализирует о загрузке DOM страницы, после которого вы уже можете манипулировать им. Обратите внимание, что событие готовности документа (ready) запускается ДО загрузки всех картинок и других медиа-данных, но после полной готовности DOM.

В сегодняшней статье мы рассмотрим основные способы проверки загрузки DOM с помощью библиотеки jQuery, а также с помощью простого JavaScript.

Способы проверки загрузки DOM в jQuery

Библиотека jQuery располагает двумя методами для проверки загрузки DOM, выполнения кода и прикрепления обработчиков событий: $(document).ready и $(window).load .

Илон Маск рекомендует:  Путь верстальщика

Эти функции проверки загрузки DOM, которые используются в jQuery (также называются jQuery DOM Ready), имеют различные виды написания.

В основном, когда вы вызываете функцию jQuery, вы передаете ее объекту документа (document). Функция возвращает расширенную версию объекта документа. Этот расширенный объект имеет функцию ready() , в которую вы передаете функцию(и) JavaScript. После готовности DOM, эти функции JavaScript будут выполнены.

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

Вариант №1.

Вариант №2.

Эта функция похожа на вариант №1 и выполняет буквально одно и то же.

Вариант №3.

Использование этого варианта помогает предотвратить конфликты с другими JavaScript платформами. Конфликты могут возникать вследствие того, что многие JavaScript библиотеки/фреймворки используют одно и то же ключевое слово — $ (символ доллара). Использование одинаково именованных функций обескураживает браузер.

Способом предотвращения подобных конфликтов можно назвать использование псевдонима для пространства имен (в примере выше это jQuery). Также можно использовать функцию $.noConflict() . Ниже 2 примера такого использования.

Вариант №4.

Этот способ также поможет вам предотвратить конфликты с другими библиотеками JavaScript.

Вариант №5.

Иногда вам нужно манипулировать картинками с помощью JavaScript, но, напомним, что $(document).ready() не позволяет это делать, поскольку функция ждет загрузки DOM, но не других ресурсов. В этом случае вам нужно использовать другую инициализацию jQuery. Ниже пример такого кода:

Событие ready запускается, когда DOM полностью загружен, а событие load запускается после загрузки не только DOM, но и всех ресурсов.

Вы также можете использовать событие загрузки документа следующим образом:

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

Использование простого JavaScript

Если вы не используете в своих скриптах библиотеки или фреймворки (например, jQuery), вы можете использовать простой JavaScript. Эта имплементация работает приблизительно в 98% браузеров (все современные браузеры и IE9+):

Для более старых браузеров вы можете использовать следующий подход: если вы поместите скрипт в конец страницы (он будет последним тегом script перед закрывающим тегом ), DOM будет готов и его статус readyState изменится на complete . После этого статуса вы можете выполнять код. Ниже пример такой реализации:

Краткий итог

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

Если вам нужно выполнять код после загрузки DOM и вы используете jQuery в своем проекте, вы можете использовать функции ready документа или load объекта окна.

Если вам нужен простой JavaScript, тогда используйте событие DOMContentLoaded .

Отложенное выполнение скрипта через N секунд на JavaScript

Продолжая тему регулярного выполнения скрипта в заданные промежутки времени, сегодня я расскажу вам, как можно просто сделать отложенное (через n-е количество времени) выполнение вашего скрипта.

Итак, всю вашу конструкцию (код) можно поместить в скрипт:

В этом случае функция анонимна. Но есть вариант и с использованием некой функции:

В обоих вариантах 2000 – это время, равное двум секундам. Именно через это время, после загрузки страницы, и произойдет выполнение вашего скрипта.

Параллельная модель и цикл событий.

На этой странице

Параллелизм в JavaScript основывается на модели «событийного цикла». Эта модель отличается от модели других языков, например C или Java.

Концепция жизненного цикла

В следующей секции объясняется теоретическая модель. Современные JavaScript движки существенно оптимизируют этот процесс.

Визуальное представление

Вызов любой функции создает контекст выполнения (Execution Context). При вызове вложенной функции создается новый контекст, а старый сохраняется в специальной структуре данных — стеке вызовов (Call Stack).

Когда вызывается функция g , создаётся первый контекст выполнения, содержащий аргументы функции g и локальные переменные. Когда g вызывает f , создаётся второй контекст с аргументами f и её локальными переменными. И этот контекст выполнения f помещается в стек вызовов выше первого. Когда f возвращает результат, верхний элемент из стека удаляется. Когда g возвращает результат, ее контекст также удалится, и стек становится пустым.

Объекты размещаются в куче. Куча — это просто имя для обозначения большой неструктурированной области памяти.

Очередь

Среда выполнения JavaScript содержит очередь задач. Эта очередь — список задач, подлежащих обработке. Каждая задача ассоциируется с некоторой функцией, которая будет вызвана, чтобы обработать эту задачу.

Когда стек полностью освобождается, самая первая задача извлекается из очереди и обрабатывается. Обработка задачи состоит в вызове ассоциированной с ней функции с параметрами, записанными в этой задаче. Как обычно, вызов функции создаёт новый контекст выполнения и заносится в стек вызовов.

Обработка задачи заканчивается, когда стек снова становится пустым. Следующая задача извлекается из очереди и начинается её обработка.

Цикл событий

Модель событийного цикла ( event loop ) называется так потому, что отслеживает новые события в цикле:

queue.waitForMessage ожидает поступления задач, если очередь пуста.

Запуск до завершения

Каждая задача выполняется полностью, прежде чем начнет обрабатываться следующая. Благодаря этому мы точно знаем: когда выполняется текущая функция – она не может быть приостановлена и будет целиком завершена до начала выполнения другого кода (который может изменить данные, с которыми работает текущая функция). Это отличает JavaScript от такого языка программирования как C. Поскольку в С функция, запущенная в отдельном потоке, в любой момент может быть остановлена, чтобы выполнить какой-то другой код в другом потоке.

У данного подхода есть и минусы. Если задача занимает слишком много времени, то веб-приложение не может обрабатывать действия пользователя в это время (например, скролл или клик). Браузер старается смягчить проблему и выводит сообщение «скрипт выполняется слишком долго» («a script is taking too long to run») и предлагает остановить его. Хорошей практикой является создание задач, которые исполняются быстро, и если возможно, разбиение одной задачи на несколько мелких.

Добавление событий в очередь

В браузерах события добавляются в очередь в любое время, если событие произошло, а так же если у него есть обработчик. В случае, если обработчика нет – событие потеряно. Так, клик по элементу, имеющему обработчик события по событию click , добавит событие в очередь, а если обработчика нет – то и событие в очередь не попадет.

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

Нулевые задержки

Нулевая задержка не дает гарантии, что обработчик выполнится через ноль миллисекунд. Вызов setTimeout с аргументом 0 (ноль) не завершится за указанное время. Выполнение зависит от количества ожидающих задач в очереди. Например, сообщение »this is just a message» из примера ниже будет выведено на консоль раньше, чем произойдет выполнение обработчика сb1. Это произойдет, потому что задержка – это минимальное время, которое требуется среде выполнения на обработку запроса.

Связь нескольких потоков между собой

Web Worker или кросс-доменный фрейм имеют свой собственный стек, кучу и очередь событий. Два отдельных событийных потока могут связываться друг с другом, только через отправку сообщений с помощью метода postMessage. Этот метод добавляет сообщение в очередь другого, если он конечно принимает их.

Никогда не блокируется

Очень интересное свойство цикла событий в JavaScript, что в отличие от множества других языков, поток выполнения никогда не блокируется. Обработка I/O обычно осуществляется с помощью событий и функций обратного вызова, поэтому даже когда приложение ожидает запрос от IndexedDB или ответ от XHR, оно может обрабатывать другие процессы, например пользовательский ввод.

Илон Маск рекомендует:  Что такое код beginpaint

Существуют хорошо известные исключения как alert или синхронный XHR, но считается хорошей практикой избегать их использования.

Javascript → Как подключить javascript файл из своего js скрипта

Пример подключения скрипта http://example.com/script.js :

Комментарии

Классная кстати фишка! Я её теперь постоянно пользуюсь.
создаю файл где пишу

для разработчика лучше вообще отключить агрегацию и любое кеширование
http://xandeadx.ru/blog/drupal/156

А разве на работающем сайте вы не вносите мелкие поправки, дополнения?

document.head.appendChild(script); тоже работает

Спасибо Вам огромное,хоть понятно стало)

Пример на Native javascript не совсем может оказаться рабочим. Например если в подключаемом скрипте написать функцию и попробовать непосредственно после document.getElementsByTagName(‘head’)[0].appendChild(script); её вызвать, то скорее всего Вы получите сообщение об ошибке ReferenceError: function is not defined
Естественно до алерта нужно вызвать свою функцию.

Вероятно это происходит из-за того что после добавления в заголовок страницы скрипта, подгрузка происходит асинхронно, почему неизвестно.

А если вызвать к примеру $(«head»).append($(»)); то подгружается нормально синхронно.

Жизненный цикл страницы: DOMContentLoaded, load, beforeunload, unload

Жизненный цикл HTML-страницы состоит из трех важных событий:

  • DOMContentLoaded — браузер полностью загрузил HTML-код страницы и построил дерево DOM . Но внешние ресурсы, такие как изображения и таблицы стилей, могут все еще загружаться;
  • onload JavaScript — браузер загрузил все ресурсы ( изображения, стили и т. д .);
  • beforeunload/unload — когда пользователь покидает страницу.

Каждое событие может использоваться для различных целей:

  • Событие DOMContentLoaded — DOM готов, поэтому обработчик может искать узлы DOM , инициализировать интерфейс.
  • Событие load — загружаются дополнительные ресурсы, и можно получать размеры изображений ( если это не указано в HTML / CSS ) и т. д.
  • Событие beforeunload/unload — пользователь покидает страницу. Можно проверить, сохранил ли пользователь изменения, и спросить его, действительно ли он хочет уйти.

Рассмотрим эти события подробнее.

DOMContentLoaded

Событие DOMContentLoaded происходит в объекте документа. Необходимо использовать addEventListener , чтобы отследить его:

В этом примере обработчик DOMContentLoaded запускается при загрузке документа ( не при JavaScript onload ), и не ждет полной загрузки страницы. Таким образом, предупреждение сообщает, что размер изображений равен нулю.

На первый взгляд событие DOMContentLoaded простое. Но есть несколько особенностей.

DOMContentLoaded и скрипты

Когда браузер загружает HTML и встречает в коде

Причина этого заключается в том, что скрипту могут понадобиться координаты и другие, зависящие от стиля свойства элементов, как в приведенном выше примере. Естественно, он должен ждать загрузки CSS .

Поскольку DOMContentLoaded ожидает загрузки скриптов ( document onload JavaScript ), он должен дождаться и загрузки стилей.

Автоматическое заполнение браузерами

Firefox , Chrome и Opera автоматически заполняют поля форм для DOMContentLoaded . Например, если страница имеет форму с полями для ввода имени пользователя и пароля, а браузер запомнил их значения, DOMContentLoaded может попытаться автоматически их заполнить ( если это одобрено пользователем ).

Поэтому, кроме задержки до полной загрузки и выполнения скриптов, DOMContentLoaded может задерживаться и из-за автоматического заполнения полей форм. Вы могли сталкиваться с этим на некоторых сайтах: поля ввода логина / пароля не обновляются автоматически, и возникает задержка до полной загрузки страницы. На самом деле это задержка события DOMContentLoaded .

Одно из незначительных преимуществ использования атрибутов async и defer для внешних скриптов заключается в том, что они не блокируют DOMContentLoaded и позволяют избежать задержки, связанной с автоматическим заполнением форм.

window.onload

Событие window onload JavaScript запускается после полной загрузки страницы, включая стили, изображения и другие ресурсы.

В приведенном ниже примере правильно отображаются размеры изображений, так как window.onload ожидает загрузки всех изображений:

window.onunload

Когда посетитель покидает страницу, для объекта window запускается событие unload . При этом можно выполнить определенные действия, не связанные с задержкой. Например, закрыть всплывающие окна. Но нельзя отменить переход на другую страницу. Для этого необходимо использовать другое событие — onbeforeunload .

window.onbeforeunload

Если посетитель покидает страницу или пытается закрыть окно, обработчик beforeunload может запросить дополнительное подтверждение. Этот обработчик возвращает строку с вопросом. Браузер отобразит ее.

Некоторые браузеры, такие как Chrome и Firefox , игнорируют заданное значение и отображают собственное сообщение. Делается это из соображений безопасности, чтобы защитить пользователя от мошеннических и хакерских сообщений при наступлении события JavaScript onload .

readyState

Что произойдет, если установить обработчик DOMContentLoaded после загрузки документа? Естественно, он никогда не запустится.

Бывают случаи, когда непонятно, готов ли документ. Например, внешний скрипт с атрибутом async загружается и запускается асинхронно. В зависимости от сети он может загружаться и выполняться до завершения загрузки документа или после этого. Поэтому необходимо знать текущее состояние документа.

Свойство document.readyState предоставляет такую информацию. Возможны три значения:

  • « loading » — документ загружается;
  • « interactive » — документ полностью считан;
  • « complete » — документ полностью считан и все ресурсы ( например, изображения ) загружены.

Так можно проверить значение document.readyState и настроить обработчик или выполнить код немедленно, как только он будет готов.

Например, следующим образом:

Событие readystatechange запускается при изменении состояния. Можно выводить все эти состояния следующим образом:

Событие readystatechange является альтернативным методом отслеживания состояния загрузки документа, оно было введено давно. В настоящее время оно редко используется, но рассмотрим его для полноты картины.

Как размещается readystatechange по отношению к другим событиям? Чтобы продемонстрировать порядок их срабатывания, ниже приводится пример с , и обработчиками, которые регистрируют события ( JavaScript onload и другие ):

Демо-версию можно найти на sandbox .

Стандартная последовательность событий:

  1. [1] инициализация readyState:loading;
  2. [2] readyState:interactive;
  3. [2] DOMContentLoaded;
  4. [3] iframe onload;
  5. [4] readyState:complete;
  6. [4] img onload;
  7. [4] window onload JavaScript.

Цифры в квадратных скобках обозначают приблизительное время, когда это происходит. Реальное время немного больше, но события с одинаковой цифрой срабатывают примерно в одно и то же время ( ± несколько миллисекунд ).

Document.readyState принимает состояние interactive непосредственно перед DOMContentLoaded . Эти два события фактически означают одно и то же.

Document.readyState завершается, когда загружаются все ресурсы ( iframe и img ). Мы видим, что это происходит примерно в то же время, что и img.onload ( img — последний ресурс ) и window.onload . Переключение на состояние complete означает то же, что и window.onload . Разница в том, что window.onload всегда запускается после всех других обработчиков load .

Заключение

События жизненного цикла страницы:

  • DOMContentLoaded инициирует события в документе, когда DOM готов. На этом этапе можно применить к элементам JavaScript :

— Выполняются все скрипты, кроме внешних, подключаемых с использованием атрибутов async или defer ;
— Изображения и другие ресурсы могут увеличивать время загрузки.

  • Когда страница и ресурсы загружены, для объекта window запускается событие load . Мы редко его используем, потому что обычно не нужно так долго ждать;
  • Событие JavaScript onload запускается для объекта window , когда пользователь хочет покинуть страницу. Если при этом возвращается строка, браузер отображает сообщение с вопросом о том, действительно ли пользователь хочет покинуть страницу;
  • Событие unload запускается для объекта window , когда пользователь окончательно покидает страницу. В обработчике можно выполнять простые действия, которые не связаны с задержками или запросом пользователя. Из-за этого ограничения данное событие используется редко;
  • Document.readyState — это текущее состояние документа, изменения могут отслеживаться в событии readystatechange :

— loading — документ загружается;
— interactive — документ анализируется. Это происходит примерно в то же время, что и событие DOMContentLoaded , но непосредственно перед ним;
— complete — документ и все ресурсы загружены. Происходит примерно в то же время, что и событие window onload JavaScript , но непосредственно перед ним.

Данная публикация представляет собой перевод статьи « Page lifecycle DOMContentLoaded, load, beforeunload, unload » , подготовленной дружной командой проекта Интернет-технологии.ру

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL