js дождаться загрузки скрипта

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

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

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

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

DOMContentLoaded

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

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

DOMContentLoaded и скрипты

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

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

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

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

window.onload

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

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

window.onunload

window.onbeforeunload

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

readyState

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

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

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

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

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

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

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

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

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

Заключение

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

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

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

Источник

Погружение в темные воды загрузки скриптов

Введение

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

Нет, подождите, вернитесь! Я знаю, что это звучит заурядно и просто, но помните, что это происходит в браузере, где теоретически простое превращается в набор причуд, определенных наследственностью. Знание этих причуд поможет вам выбрать самый быстрый, наименее разрушительный способ загрузки скриптов. Если вы спешите, то можете перейти сразу к краткому справочнику в конце статьи.

Для затравки, вот как спецификация определяет различные способы загрузки и выполнения скриптов:

js дождаться загрузки скрипта

Как и все спецификации WHATWG, на первый взгляд данная спецификация выглядит как последствия кассетной бомбы на фабрике Scrabble. Но, прочитав ее на 5 раз и вытерев кровь из своих глаз, начинаешь находить ее довольно интересной:

Мое первое подключение скрипта

Ах, блаженная простота. В данном случае браузер скачает оба скрипта параллельно и выполнит их как можно скорее, сохраняя заданный порядок. «2.js» не будет выполняться пока не выполнится «1.js» (или не сможет этого сделать), «1.js» не выполнится пока не выполнится предыдущий скрипт или стиль, и т.д. и т.п.

Вот почему гуру и специалисты производительности советуют размещать элементы script в конце документа, потому что это блокирует меньше всего контента. К сожалению, это означает, что ваш скрипт не будет увиден браузером до того времени, как будет скачен весь HTML, а также уже запущена загрузка CSS, картинок и iframe-ов. Современные браузеры достаточно умны, чтобы отдавать приоритет JavaScript над визуальной частью, но мы можем сделать лучше.

Спасибо, IE! (нет, я это без сарказма)

WHATWG сделали это поведение явным, объявив, что «defer» не будет иметь никакого эффекта на скрипты, которые были добавлены динамически или не имеют «src». В противном случае, скрипты с «defer» должны запускаться в заданном порядке после того, как документ был распарсен.

Спасибо, IE! (ну ладно, теперь с сарказмом)

Одно дали — другое отобрали. К сожалению, есть неприятный баг в IE4-9, который может спровоцировать выполнение скриптов в неверном порядке. Вот что происходит:

Допустим, что на странице есть параграф, ожидаемый порядок логов — [1, 2, 3], но в IE9 и ниже результат будет [1, 3, 2]. Некоторые операции DOM вынуждают IE приостановить выполнение текущего скрипта и перед продолжением начать выполнение других скриптов в очереди.

HTML5 спешит на помощь

HTML5 дал нам новый атрибут «async», который предполагает, что вы также не используете document.write, но при этом не ожидает окончания парсинга документа. Браузер параллельно скачает оба скрипта и выполнит их как можно скорее.

К сожалению, так как они постараются выполниться максимально скоро, «2.js» может выполниться раньше «1.js». Это отлично, если они не зависят друг от друга. Например, если «1.js» — это отслеживающий скрипт, не имеющий ничего общего с «2.js». Но если «1.js» — это CDN-копия jQuery, от которой зависит «2.js», то ваша страница будет устлана ошибками, как после кассетной бомбы в… я не знаю… здесь я ничего не придумал.

Я знаю, нам нужна JavaScript-библиотека!

В Святом Граале содержится набор скриптов, загружающихся сразу, без блокирования отрисовки страницы и выполняющихся максимально скоро, в том порядке, в котором мы их добавили. К сожалению, HTML ненавидит вас и не позволит вам этого сделать.

Проблема была решена с помощью JavaScript на разный манер. Некоторые способы требовали от вас вносить изменения в JavaScript, оборачивать всё в callback, который библиотека вызовет в правильном порядке (например, RequireJS). Другие использовали XHR для параллельной загрузки, а затем eval() в нужном порядке, который не работает для скриптов на другом домене, если там нет заголовка CORS и поддержки его в браузере. Некоторые использовали даже супер-магические хаки, как это было сделано в последнем LabJS.

Хаки всяческим образом обманывали браузер, чтобы тот загружал ресурс, вызывая при этом событие по окончанию загрузки, но не начинал его выполнение. В LabJS скрипт сначала добавлялся с некорректным mime-типом, например
Скрипты, которые созданы и добавлены динамически, асинхронные по-умолчанию, они не блокируют отрисовку и выполняются сразу после загрузки, что означает, что они могут появиться в неверном порядке. Однако мы можем явно пометить их неасинхронными:

Это даст нашим скриптам сочетание с поведением, которое не может быть достигнуто чистым HTML. Явно заданные неасинхронными, скрипты добавляются в очередь на выполнение, такую же, как они попадали в нашем первом примере на чистом HTML. Однако, создаваемые динамически, они будут выполняться вне парсинга документа, что не будет блокировать отрисовку, пока они будут загружаться (не путайте неасинхронную загрузку скрипта с синхронным XHR, что никогда не является хорошей вещью).

Скрипт выше должен быть встроен в head страниц, начиная очередь загрузок как можно раньше, без нарушения постепенной отрисовки, и начиная выполнять как можно раньше, в заданном вами порядке. «2.js» может свободно загружаться до «1.js», но он не будет выполнен до тех пор, пока «1.js» успешно не скачается и выполнится или не сможет сделать что-либо из этого. Ура! Асинхронная загрузка, но выполнение по порядку!

Загрузка скриптов этим методом поддерживается везде, где поддерживается атрибут async, за исключением Safari 5.0 (на 5.1 все хорошо). Кроме того все версии Firefox и Opera, которые не поддерживают атрибут async, все равно выполняют динамически-добавленные скрипты в правильном порядке.

Это самый быстрый способ загружать скрипты, так? Так?

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

Мы можем добавить обнаружаемость обратно, поместив это в head документа:

Эта статья меня удручает

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

С появлением HTTP2/SPDY вы сможете уменьшить накладные ресурсы до точки, где доставка скриптов в маленьких самостоятельно-кэшированных файлах будет самым быстрым способом. Только представьте:

Каждый enhancement-скрипт имеет дело с конкретным компонентом страницы, но требует вспомогательные функции в dependencies.js. В идеале, мы хотим загрузить все асинхронно, затем выполнить enhancement-скрипт как можно раньше, в любом порядке, но после dependencies.js. Это прогрессивное прогрессивное улучшение!

К сожалению, нет декларативного способа для того, чтобы достичь этого, только если модифицировать сами скрипты для отслеживания состояния загрузки dependencies.js. Даже async=false не решит эту проблему, потому что выполнение enhancement-10.js будет заблокировано на 1-9. По факту, есть только один браузер, в котором можно достичь этого без хаков…

У IE есть идея!

IE грузит скрипты не так, как другие браузеры.

IE начинает закачивать «whatever.js» сейчас, другие же браузеры не начнут загрузку до того момента, пока скрипт не будет добавлен к документу. У IE также есть событие «readystatechange» и свойство «readystate», которые сообщают о процессе загрузки. Это на самом деле очень полезно, потому что позволяет нам управлять загрузкой и выполнением скриптов независимо друг от друга.

Хватит! Как я должен загружать скрипты?

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

Именно этот. В конце элемента body. Да, быть веб-разработчиком — это как быть царем Сизифом (бум! 100 хипстерских очков за упоминание греческой мифологии!). Ограничения HTML и браузеров не позволяют нам сделать сильно лучше.

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

Иуу, должно быть что-то получше, что мы можем использовать сейчас?

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

Во-первых, мы добавим объявление subresource для предзагрузчиков:

Спецификация говорит: Скачивай вместе, выполняй по порядку после любого ожидающего CSS, блокируй отрисовку, пока не закончишь
Браузер отвечает: Да, сэр!

Defer

Спецификация говорит: Скачивай вместе, выполняй по порядку до DOMContentLoaded. Игнорируй «defer» для скриптов без «src».
IE

Источник

Страница: DOMContentLoaded, load, beforeunload, unload

У жизненного цикла HTML-страницы есть три важных события:

Каждое из этих событий может быть полезно:

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

DOMContentLoaded

Но он не дожидается, пока загрузится изображение. Поэтому alert покажет нулевой размер.

На первый взгляд событие DOMContentLoaded очень простое. DOM-дерево готово – получаем событие. Хотя тут есть несколько особенностей.

DOMContentLoaded и скрипты

Когда браузер обрабатывает HTML-документ и встречает тег

В примере выше мы сначала увидим «Библиотека загружена…», а затем «DOM готов!» (все скрипты выполнены).

Есть два исключения из этого правила:

DOMContentLoaded и стили

Внешние таблицы стилей не затрагивают DOM, поэтому DOMContentLoaded их не ждёт.

Но здесь есть подводный камень. Если после стилей у нас есть скрипт, то этот скрипт должен дождаться, пока загрузятся стили:

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

Так как DOMContentLoaded дожидается скриптов, то теперь он так же дожидается и стилей перед ними.

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

Например, если на странице есть форма логина и пароля и браузер запомнил значения, то при наступлении DOMContentLoaded он попытается заполнить их (если получил разрешение от пользователя).

window.onload

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

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

window.onunload

Обычно здесь отсылают статистику.

Предположим, мы собрали данные о том, как используется страница: клики, прокрутка, просмотры областей страницы и так далее.

Естественно, событие unload – это тот момент, когда пользователь нас покидает и мы хотим сохранить эти данные.

Его можно использовать вот так:

К тому моменту, как sendBeacon завершится, браузер наверняка уже покинет страницу, так что возможности обработать ответ сервера не будет (для статистики он обычно пустой).

Для таких запросов с закрывающейся страницей есть специальный флаг keepalive в методе fetch для общих сетевых запросов. Вы можете найти больше информации в главе Fetch API.

window.onbeforeunload

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

Если мы отменим это событие, то браузер спросит посетителя, уверен ли он.

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

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

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

readyState

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

Естественно, он никогда не запустится.

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

Свойство document.readyState показывает нам текущее состояние загрузки.

Есть три возможных значения:

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

Событие readystatechange – альтернативный вариант отслеживания состояния загрузки документа, который появился очень давно. На сегодняшний день он используется редко.

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

Рабочий пример есть в песочнице.

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

Источник

События при загрузке HTML-документа

Рассмотрим работу этих событий подробнее и начнем с первого DOMContentLoaded. Возьмем вот такой HTML-документ с отображением рисунка:

И добавим обработчик для DOMContentLoaded. Это можно сделать только через метод addEventListener объекта document:

В обработчике мы выводим размер изображения. Обновляем документ и видим, что размер нулевой. Это как раз и говорит о том, что событие DOMContentLoaded возникает до загрузки ресурсов (если, конечно, они не были закэшированы).

В целом, все понятно и просто. Но, как всегда, есть один нюанс. Данное событие отрабатывает только после выполнения всех скриптов, записанных в HTML-документе. Например, если мы добавим вот такой скрипт в конец документа:

То сначала сработает он, а потом уже событие DOMContentLoaded. Обновляем страницу и видим этот эффект.

Почему разработчики языка JavaScript реализовали такую последовательность вызовов? Дело в том, что в момент загрузки страницы скрипты могут вносить изменения в DOM-дерево: удалять или добавлять какие-то элементы. Поэтому, нужно сначала полностью сформировать DOM, а значит, выполнить скрипты, и только потом сгенерировать сообщение DOMContentLoaded. Так что такое поведение браузера вполне логично.

С каскадными таблицами стилей (CSS) все несколько иначе. Изначально, событие DOMContentLoaded возникает не дожидаясь загрузки стилей, так как они непосредственно не затрагивают DOM-дерево. Однако, если на странице есть скрипт, который использует CSS-стили, например, такой:

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

Следующее событие load для объекта window работает очень просто: оно генерируется браузером, когда HTML-документ полностью загружен вместе со всеми связанными с ним ресурсами:

Здесь при обновлении документа мы увидим полные размеры изображения.

Следующее событие unload объекта window выполняется когда пользователь практически покинул HTML-страницу. Обычно, в этот момент отправляется статистика поведения пользователя на странице серверу:

Если мы теперь станем обновлять станицу, то в консоли будет появляться данное сообщение. К сожалению, продемонстрировать работу этого события как то приятнее не получается. Поэтому, далее, пара слов теории. Для отправки данных серверу в объекте navigator существует такой специальный метод:

Здесь url – это путь к скрипту на сервере, который будет принимать данные data. Особенность этого метода в том, что при закрытии страницы нет необходимости дожидаться окончания его работы. Браузер будет его выполнять в фоне даже при отсутствии ранее открытого документа. Поэтому, если вы хотите что-то отправить на сервер при закрытии HTML-страницы, то это лучше всего делать через этот метод. На практике он реализуется примерно так:

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

объекта window следующим образом:

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

Ранее, в браузерах можно было писать свои сообщения в таких окнах, примерно так:

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

readyState

В заключение занятия отметим свойство

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

По аналогии могут быть обработаны и остальные свойства.

Для полноты картины пару слов о событии readystatechange, которое появилось до событий

DOMContentLoaded, load, unload, beforeunload

и в старых версиях JavaScript процесс загрузки документа контролировался через него. Например, так:

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

Итак, на этом занятии мы с вами рассмотрели события

DOMContentLoaded, load, unload, beforeunload

и поговорили о свойстве

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

Видео по теме

js дождаться загрузки скрипта

JavaScipt (DOM) #1: объектная модель документа DOM и BOM

js дождаться загрузки скрипта

js дождаться загрузки скрипта

JavaScipt (DOM) #3: методы поиска элементов в DOM: querySelector, querySelectorAll, getElementById

js дождаться загрузки скрипта

JavaScipt (DOM) #4: свойства DOM-узлов: nodeName, innerHTML, outerHTML, data, textContent, hidden

js дождаться загрузки скрипта

JavaScipt (DOM) #5: работа с нестандартными свойствами DOM-элементов: getAttribute, setAttribute, dataset

js дождаться загрузки скрипта

JavaScipt (DOM) #6: создание и добавление элементов DOM createElement, append, remove, insertAdjacentHTML

js дождаться загрузки скрипта

js дождаться загрузки скрипта

js дождаться загрузки скрипта

JavaScipt (DOM) #9: HTML-документ: размеры (clientWidth, innerWidth), положение (pageYOffset, scrollBy)

js дождаться загрузки скрипта

js дождаться загрузки скрипта

JavaScipt (DOM) #11: обработчики событий: onclick, addEventListener, removeEventListener, event

js дождаться загрузки скрипта

JavaScipt (DOM) #12: погружение и всплытие событий: stopPropagation, stopImmediatePropagation, eventPhase

js дождаться загрузки скрипта

js дождаться загрузки скрипта

JavaScipt (DOM) #14: события мыши mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter

js дождаться загрузки скрипта

JavaScipt (DOM) #15: события клавиатуры keydown, keyup, событие скроллинга scroll

js дождаться загрузки скрипта

js дождаться загрузки скрипта

js дождаться загрузки скрипта

JavaScipt (DOM) #18: события change, input, cut, copy, paste, submit элементов input и select

js дождаться загрузки скрипта

js дождаться загрузки скрипта

JavaScipt (DOM) #20: события load, error; атрибуты async, defer тега script

js дождаться загрузки скрипта

JavaScipt (DOM) #21: пример предзагрузки изображений с помощью javascript

js дождаться загрузки скрипта

JavaScipt (DOM) #22: пример создания начала игры арканоид

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

Источник

Запуск скрипта после загрузки страницы (DOM)

Есть скрипт, который должен запуститься после загрузки DOM, так как в нём есть обращение к DOM:

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

js дождаться загрузки скрипта

2 ответа 2

Для тех, кто не знает, почему не работают скрипты с обращением к элементам вида :

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

Особенность языка Javascript в том, что его код выполняется последовательно, строка за строкой, как они написаны в исходном коде.

Варианты решения данного вопроса:

Один из простых способов ― перенести в body после всех элементов. При таком расположении сначала загрузится DOM, а потом скрипт. Пример:

Но у этого метода есть недостаток: если на странице сайта куча картинок, которые грузятся пол часа, то скрипт выполнится только после того, как загрузятся все картинки и это может занят много времени.

Ещё одним минусом является то, что нельзя указывать несколько функций таким образом. Т.е. если вы два раза использовали window.onload в коде, то вторая функция сотрёт первую. Но, чтобы это исправить, я сочинил интересный костыль:

Интересный вариант ― что-то между первым и вторым пунктом. Создать особую функцию и вызывать её через скрипт в конце body. Пример:

Поддержка этого метода начинается с IE9+

Ну и подошли варианты с библиотеками. И первая наша библиотека JQuery ScriptJava. Пример:

Самый действенный вариант ― самописная функция со enStackOverflow. Работает в IE8:

var ready = (function()<

> // The DOM ready check for Internet Explorer function doScrollCheck()

И наконец самый странный и не всегда рабочий вариант ― использовать setTimeout. Пример:

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *