В мире технологий решения, которые мы находим, настолько же хороши, насколько и проблемы, которые они решают. Я просто люблю иронию здесь. То, что решает проблему однажды, может фактически только маскировать симптомы большего осложнения. Позвольте мне уточнить …
Сценарии и загрузка
Когда в 1999 году я впервые начал программировать на JavaScript, никто не задумывался о синхронизации компонентов при их загрузке. Мы поместили все наши скрипты в раздел <head>
и связали все в window.onload
. Мы сделали это, потому что это была полученная мудрость, и полученная мудрость тоже еще много об этом не думала, потому что проблема никогда не возникала. Люди практически ничего не делали с JavaScript. О, всегда было исключение, как все скользящее, все вращающееся место Аарона Будмана ; Это заставило всех нас стыдиться и работать лучше всего в Netscape 4. По большей части скрипты использовались только для открытия всплывающих окон, эффектов прокрутки изображений и случайных выпадающих меню. Но со временем страницы становились больше и сценарии стали более изощренными — и люди использовали все больше и больше изображений, потому что соединения были быстрее — было очевидно, что ожидание загрузки всего до запуска сценариев теперь стало недопустимой задержкой. Примерно в 2005 году появилось множество решений ; наиболее удобными и понятными из них стали стандартные подходы, встроенные в библиотеки повсюду. Самым заметным, конечно, является то, что браузеры предоставляют напрямую: событие DOMContentLoaded
.
Ирония
DOMContentLoaded
часть DOMContentLoaded
состоит в том, что он запускается до загрузки изображений — как только DOM становится доступным. По крайней мере, так говорит название; на самом деле, это не когда он срабатывает вообще. На самом деле он срабатывает именно тогда, когда DOM — и внешние зависимости, которые могут повлиять на DOM — разрешились. На практике это означает, что это событие, далеко от обхода зависимостей, фактически только обходит изображения; все неотложенные сценарии и таблицы стилей на странице должны быть загружены и проанализированы до DOMContentLoaded
DOMContentLoaded. Когда мы впервые начали использовать DOMContentLoaded
, это не было очевидно. Я начал всерьез задумываться об этом, потому что оказался в ситуации, когда мне нужно было выполнить сценарии, как только станет доступен <head>
, прежде чем сценарии и таблицы стилей будут проанализированы. (Точнее, раньше этого не было, просто не могло быть.) Когда DOMContentLoaded
стал стандартным подходом к написанию сценариев, мы думали только об изображениях в основном. Но образы больше не враги. Когда вы ожидаете окончания загрузки страницы, как обычно, ждете ли вы изображений? Или это полдюжины сценариев синдикации рекламы, из полдюжины, не особо мощных, рекламных серверов? Все это должно разрешиться до того, как DOMContentLoaded
сработает, и в наши дни это намного дольше, чем изображения. Поскольку задержка зависит не от размера зависимостей, она ожидает ответа от всех этих серверов.
Следующая глава
Я провел небольшое исследование, чтобы выяснить, говорил ли кто-либо еще об этой проблеме, и обнаружил, что идет небольшая дискуссия о том, должен ли DOMContentLoaded
до или после таблиц стилей . (Очевидно, что Opera отличается от других браузеров, и Firefox может быть несовместимым.) Лично я вижу, какой подход может быть полезным в зависимости от обстоятельств. Все это напомнило о решении, которое я разработал в 2005 году, в качестве моего вклада в оригинал. вопрос. Называемый domFunction , он был основан на асинхронном таймере, который просто проверяет наличие элемента <body>
(чтобы гарантировать, что можно безопасно ссылаться и создавать вещи в DOM ) и запускает обратный вызов, как только он там появляется. Он никогда не завоевывал популярность в то время, возможно, потому, что он не так прост или элегантен в использовании, как другие подходы. К счастью, это решение также решает мою новую проблему! Это действительно агностик в отношении зависимостей, и это то, что я решил адаптировать для моего последнего сценария. (Хотя исходное решение циклически повторяется каждые 250 мс, я увеличил его до 20 мс, потому что я знал, что это будет минимальное ожидание <head>
, и на практике требуется всего одна-две итерации.) Его также можно адаптировать к проверить наличие других конкретных зависимостей; Об этом я буду думать в течение следующих нескольких недель. Он может проверять наличие <head>
, <body>
, коллекции styleSheets
и / или отображаемого приложения CSS (с помощью computedStyle
computedStyle); он может проверять наличие определенных элементов или определенных объектов сценариев, или того, что вам нужно, чтобы ждать. Возможности интригуют. Не менее интригующими являются возможности, предоставляемые событиями мутации DOM 2 и / или общими наблюдателями объектов . Возможно, мы могли бы наблюдать за изменениями в состоянии всего документа, чтобы узнать, находятся ли конкретные узлы в состоянии, которое будет использоваться сценариями. Или узнать, были ли они затронуты применением определенного CSS. Это все хорошие идеи, так что посмотрим. Миниатюра кредит: Голдберг
Если вы хотите узнать больше от Джеймса, подпишитесь на нашу еженедельную техническую новостную рассылку Tech Times .