Лекция
Привет, Вы узнаете о том , что такое event loop, Разберем основные их виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое event loop, javascript, web api, цикл событий, page lifecycle api , настоятельно рекомендую прочитать все из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend).
Что происходит, когда вы вводите URL-адрес в адресной строке браузера?
это можно увидить на это диаграмме
Как думаете, что произойдет, если запустить в консоли браузера этот фрагмент кода?
function foo() { setTimeout(foo, 0); } foo();
А этот?
function foo() { Promise.resolve().then(foo); } foo();
Если вы также, как и я, прочитали кучу статей про Event Loop, Main Thread, таски, микротаски и прочее, но затрудняетесь ответить на вопросы выше — эта статья для вас.
Итак, приступим. Код каждой HTML-страницы в браузере выполняется в Main Thread. Main Thread — это основной поток, где браузер выполняет JS, делает перерисовки, обрабатывает пользовательские действия и многое другое. По сути, это то место, где движок JS интегрирован в браузер.
Проще всего разобраться, глядя на схему:
Рисунок 1
Мы видим, что единственное место, через которое задачи могут попасть в Call Stack и выполниться — это Event Loop. Представьте, что вы оказались на его месте. И ваша работа успевать 'разгребать' задачи. Задачи могут быть двух типов:
function foo() { setTimeout(foo, 0); } foo();
Мы видим, что функция foo вызывает сама себя рекурсивно через setTimeout внутри, но при каждом вызове она создает задачу заказчика Tasks. Как мы помним, в цикле Event Loop при выполнении очереди задач от Tasks берет только 1 задачу в цикл. И далее происходит выполнение задач от Microtasks и Render. Поэтому этот фрагмент кода не заставит Event Loop страдать и вечно разгребать его задачи. Но будет подкидывать новую задачу для заказчика Tasks на каждом круге.
Давайте попробуем выполнить этот скрипт в браузере Google Chrome. Для этого я создал простой HTML-документ и подключил в нем script.js с этим фрагментом кода. После открытия документа заходим в инструменты разработчика, и открываем вкладку Perfomance и жмем там кнопку 'start profiling and reload page':
Рисунок 4
Видим, что задачи от Tasks выполняются по одной в цикл, примерно раз в 4ms.
Рассмотрим вторую задачку:
function foo() { Promise.resolve().then(foo); } foo();
Здесь мы видим тоже самое, что и в примере выше, но вызов foo добавляет задачи от Microtasks, а они выполняются все, пока не закончатся. А это значит, что пока Event Loop не закончит их, перейти к следующему заказчику он не сможет :( И мы видим снова грустную картинку.
Взглянем на это в интрументах разработчкика:
Рисунок 5
Мы видим, что микротаски выполняются примерно раз в 0.1ms, и это в 40 раз быстрее, чем очередь Tasks. Все потому, что они выполняются все и сразу. В нашем примере очередь движется бесконечно. Для визуализации я уменьшил ее до 100 000 итераций.
Концепция жизненного цикла JS
. Современные JavaScript движки внедряют/имплементируют и существенно оптимизируют этот процесс.
Для лучшего визуального представления работы Event loop,
Вызов любой функции создает контекст выполнения (Execution Context). При вызове вложенной функции создается новый контекст, а старый сохраняется в специальной структуре данных - стеке вызовов (Call Stack).
function f(b) { var a = 12; return a + b + 35; } function g(x) { var m = 4; return f(m * x); } g(21);
Объекты размещаются в куче. Куча — это просто имя для обозначения большой неструктурированной области памяти.
Среда выполнения JavaScript содержит очередь задач. Эта очередь — список задач, подлежащих обработке. Каждая задача ассоциируется с некоторой функцией, которая будет вызвана, чтобы обработать эту задачу.
Когда стек полностью освобождается, самая первая задача извлекается из очереди и обрабатывается. Обработка задачи состоит в вызове ассоциированной с ней функции с параметрами, записанными в этой задаче. Как обычно, вызов функции создает новый контекст выполнения и заносится в стек вызовов.
Обработка задачи заканчивается, когда стек снова становится пустым. Следующая задача извлекается из очереди и начинается ее обработка.
Модель событийного цикла (event loop) называется так потому, что отслеживает новые события в цикле:
while(queue.waitForMessage()){ queue.processNextMessage(); }
queue.waitForMessage ожидает поступления задач, если очередь пуста.
Каждая задача выполняется полностью, прежде чем начнет обрабатываться следующая. Благодаря этому мы точно знаем: когда выполняется текущая функция – она не может быть приостановлена и будет целиком завершена до начала выполнения другого кода (который может изменить данные, с которыми работает текущая функция). Это отличает JavaScript от такого языка программирования как C. Поскольку в С функция, запущенная в отдельном потоке, в любой момент может быть остановлена, чтобы выполнить какой-то другой код в другом потоке.
У данного подхода есть и минусы. Если задача занимает слишком много времени, то веб-приложение не может обрабатывать действия пользователя в это время (например, скролл или клик). Браузер старается смягчить проблему и выводит сообщение "скрипт выполняется слишком долго" ("a script is taking too long to run") и предлагает остановить его. Хорошей практикой является создание задач, которые исполняются быстро, и если возможно, разбиение одной задачи на несколько мелких.
В браузерах события добавляются в очередь в любое время, если событие произошло, а так же если у него есть обработчик. В случае, если обработчика нет – событие потеряно. Так, клик по элементу, имеющему обработчик события по событию click , добавит событие в очередь, а если обработчика нет – то и событие в очередь не попадет.
Вызов setTimeout добавит событие в очередь по прошествии времени, указанного во втором аргументе вызова. Если очередь событий на тот момент будет пуста, то событие обработается сразу же, в противном случае событию функции setTimeout придется ожидать завершения обработки остальных событий в очереди. Именно поэтому второй аргумент setTimeout корректно считать не временем, через которое выполнится функция из первого аргумента, а минимальное время, через которое она сможет выполниться.
(function () { console.log('this is the start'); setTimeout(function cb() { console.log('this is a msg from call back'); }); console.log('this is just a message'); setTimeout(function cb1() { console.log('this is a msg from call back1'); }, 0); console.log('this is the end'); })(); // "this is the start" // "this is just a message" // "this is the end" // "this is a msg from call back" // "this is a msg from call back1"
Web Worker или кросс-доменный фрейм имеют свой собственный стек, кучу и очередь событий. Два отдельных событийных потока могут связываться друг с другом, только через отправку сообщений с помощью метода postMessage. Этот метод добавляет сообщение в очередь другого, если он конечно принимает их.
Очень интересное свойство цикла событий в JavaScript, что в отличие от множества других языков, поток выполнения никогда не блокируется. Обработка I/O обычно осуществляется с помощью событий и функций обратного вызова, поэтому даже когда приложение ожидает запрос от IndexedDB или ответ от XHR, оно может обрабатывать другие процессы, например пользовательский ввод.
Существуют хорошо известные исключения как alert или синхронный XHR, но считается хорошей практикой избегать их использования.
Жизненный цикл приложения - это ключевой способ управления ресурсами современных операционных систем. В Android, iOS и последних версиях Windows приложения могут быть запущены и остановлены в любой момент ОС. Это позволяет этим платформам оптимизировать и перераспределять ресурсы там, где они наиболее выгодны пользователю.
В Интернете такого жизненного цикла исторически не существовало, и приложения можно было поддерживать бесконечно. При большом количестве работающих веб-страниц критически важные системные ресурсы, такие как память, ЦП, аккумулятор и сеть, могут быть превышены по подписке, что ухудшает работу конечных пользователей.
Хотя на веб-платформе уже давно есть события, связанные с состояниями жизненного цикла, такие как load
, unload
и visibilitychange
- эти события позволяют разработчикам реагировать только на инициированные пользователем изменения состояния жизненного цикла. Чтобы Интернет мог надежно работать на маломощных устройствах (и в целом уделять больше внимания ресурсам на всех платформах), браузерам необходим способ упреждающего восстановления и перераспределения системных ресурсов.
Фактически, браузеры сегодня уже принимают активные меры по экономии ресурсов для страниц на фоновых вкладках, и многие браузеры (особенно Chrome) хотели бы делать гораздо больше - чтобы уменьшить общий объем ресурсов.
Проблема в том, что разработчики в настоящее время не имеют возможности подготовиться к такого рода вмешательствам, инициируемым системой, или даже знать, что они происходят. Это означает, что браузеры должны быть консервативными, иначе веб-страницы могут сломаться.
Page Lifecycle API пытается решить эту проблему:
Это решение обеспечивает предсказуемость, необходимую веб-разработчикам для создания приложений, устойчивых к вмешательству системы, и позволяет браузерам более агрессивно оптимизировать системные ресурсы, что в конечном итоге приносит пользу всем веб-пользователям.
В оставшейся части этого поста будут представлены новые функции жизненного цикла страницы, доступные в Chrome 68, и исследовано, как они связаны со всеми существующими состояниями и событиями веб-платформы. В нем также будут даны рекомендации и передовые методы работы, которую разработчики должны (и не должны) выполнять в каждом штате.
Все состояния жизненного цикла страницы являются дискретными и взаимоисключающими, то есть страница может одновременно находиться только в одном состоянии. И большинство изменений в состоянии жизненного цикла страницы обычно можно наблюдать через события DOM (см. Рекомендации разработчика для каждого состояния для исключений).
В следующей таблице подробно объясняется каждое состояние. В нем также перечислены возможные состояния, которые могут наступить до и после, а также события, которые разработчики могут использовать для отслеживания изменений.
State | Описание |
---|---|
Active |
Страница находится в активном состоянии, если она видна и имеет фокус ввода. Возможные предыдущие состояния: Возможные следующие состояния: |
Passive |
Страница находится в passive состоянии, если она видна и не имеет фокуса ввода. Возможные предыдущие состояния: Возможные следующие состояния: |
Hidden |
Страница находится в скрытом состоянии, если она не видна и не была заморожена. Возможные предыдущие состояния: Возможные следующие состояния: |
Frozen |
В frozen состоянии браузер приостанавливает выполнение замораживаемых задач на странице в очереди задач до страницы размораживается. Это означает, что такие вещи, как таймеры JavaScript и обратные вызовы выборки, не работают. Уже запущенные задачи могут завершиться (наиболее важно обратный вызов), но они могут быть ограничены в том, что они могут делать и как долго они могут работать. Браузеры замораживают страницы, чтобы сохранить загрузку ЦП / батареи / данных; они также делают это, чтобы обеспечить более быструю навигацию назад / вперед, избегая необходимости полной перезагрузки страницы. Возможные предыдущие состояния: |
Terminated |
Страница находится в завершенном состоянии после того, как она начала выгрузку и очистку из памяти браузером. Об этом говорит сайт https://intellect.icu . В этом состоянии нельзя запускать новые задачи , а выполняемые задачи могут быть прекращены, если они выполняются слишком долго. Возможные предыдущие состояния: Возможные следующие состояния: |
Discarded |
Страница находится в удаленном состоянии, когда она выгружается браузером в целях экономии ресурсов. В этом состоянии не могут выполняться никакие задачи, обратные вызовы событий или JavaScript любого типа, поскольку сбросы обычно происходят при ограниченных ресурсах, когда запуск новых процессов невозможен. В отключенном состоянии сама вкладка ( включая заголовок вкладки и значок ) обычно видна пользователю, даже если страница исчезла. Возможные предыдущие состояния: Возможные следующие состояния: |
Браузеры отправляют множество событий, но лишь небольшая их часть сигнализирует о возможном изменении состояния жизненного цикла страницы. В таблице ниже представлены все события, относящиеся к жизненному циклу, и перечислены состояния, в которые они могут переходить и из которых они могут переходить.
имя | Детали |
---|---|
focus |
Элемент DOM получил фокус. Примечание: Возможные предыдущие состояния:passive Возможные текущие состояния:active |
blur |
Элемент DOM потерял фокус. Примечание: Возможные предыдущие состояния:active Возможные текущие состояния:passive |
visibilitychange |
Стоимость документа изменилась. Это может произойти, когда пользователь переходит на новую страницу, переключает вкладки, закрывает вкладку, сворачивает или закрывает браузер или переключает приложения в мобильных операционных системах. Возможные предыдущие состояния: hidden Возможные текущие состояния: hidden |
freeze * |
Страница только что была заморожена. Любая замораживаемая задача в очередях задач страницы не будет запущена. Возможные предыдущие состояния: Возможные текущие состояния:frozen |
resume * |
Браузер возобновил остановленную страницу. Возможные предыдущие состояния:frozen Возможные текущие состояния: hidden |
pageshow |
Переход к записи истории сеанса. Это может быть либо новая загрузка страницы, либо страница, взятая из обратного кэша . Если страница была взята из Back-Forward Cache, Возможные предыдущие состояния: Возможные текущие состояния: hidden |
pagehide |
Переход к записи в истории сеанса. Если пользователь переходит на другую страницу и браузер может добавить текущую страницу в кэш обратного продвижения, чтобы использовать его позже, Возможные предыдущие состояния:hidden Возможные текущие состояния: |
beforeunload |
Окно, документ и его ресурсы будут выгружены. Документ все еще виден, и на этом этапе событие все еще можно отменить. Предупреждение: Возможные предыдущие состояния:hidden Возможные текущие состояния:terminated |
unload |
Страница выгружается. Предупреждение. Использование Возможные предыдущие состояния:hidden Возможные текущие состояния:terminated |
На приведенной выше диаграмме показаны два состояния, которые инициируются системой, а не пользователем: frozen и отклонено . Как упоминалось выше, браузеры сегодня уже иногда замораживают и удаляют скрытые вкладки (по своему усмотрению), но разработчики не имеют возможности узнать, когда это происходит.
В Chrome 68 разработчики теперь могут следить за замораживанием и размораживанием скрытой вкладки, отслеживая события freeze
и .resume
document
document.addEventListener('freeze', (event) => {
// The page is now frozen.
});
document.addEventListener('resume', (event) => {
// The page has been unfrozen.
});
В Chrome 68 document
объект теперь также включает wasDiscarded
свойство. Чтобы определить, была ли страница отброшена во время нахождения на скрытой вкладке, вы можете проверить значение этого свойства во время загрузки страницы (примечание: для повторного использования отброшенные страницы необходимо перезагрузить).
if (document.wasDiscarded) {
// Page was previously discarded by the browser while in a hidden tab.
}
Для получения консультации о том , что вещи важно сделать в freeze
и resume
событиях, а также о том , как обрабатывать и готовить для страниц отбрасываются, см рекомендации для разработчиков каждого государства .
В следующих нескольких разделах представлен обзор того, как эти новые функции вписываются в существующие состояния и события веб-платформы.
В активном , passive и hidden состояниях можно запустить код JavaScript, который определяет текущее состояние жизненного цикла страницы из существующих API веб-платформы.
const getState = () => {
if (document.visibilityState === 'hidden') {
return 'hidden';
}
if (document.hasFocus()) {
return 'active';
}
return 'passive';
};
С другой стороны, frozen и завершенное состояния могут быть обнаружены только в их соответствующем прослушивателе событий ( freeze
и pagehide
) по мере изменения состояния.
Основываясь на getState()
функции, определенной выше, вы можете наблюдать за всеми изменениями состояния жизненного цикла страницы с помощью следующего кода.
// Stores the initial state using the `getState()` function (defined above). let state = getState(); // Accepts a next state and, if there's been a state change, logs the // change to the console. It also updates the `state` value defined above. const logStateChange = (nextState) => { const prevState = state; if (nextState !== prevState) { console.log(`State change: ${prevState} >>> ${nextState}`); state = nextState; } }; // These lifecycle events can all use the same listener to observe state // changes (they call the `getState()` function to determine the next state). ['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => { window.addEventListener(type, () => logStateChange(getState()), {capture: true}); }); // The next two listeners, on the other hand, can determine the next // state from the event itself. window.addEventListener('freeze', () => { // In the freeze event, the next state is always frozen. logStateChange('frozen'); }, {capture: true}); window.addEventListener('pagehide', (event) => { if (event.persisted) { // If the event's persisted property is `true` the page is about // to enter the Back-Forward Cache, which is also in the frozen state. logStateChange('frozen'); } else { // If the event's persisted property is not `true` the page is // about to be unloaded. logStateChange('terminated'); } }, {capture: true});
getState()
функции.logStateChange()
и переходят в следующее состояние.Предупреждение! Этот код дает разные результаты в разных браузерах, поскольку порядок и надежность событий не были последовательно реализованы. Чтобы узнать, как лучше всего справиться с этими несоответствиями, см. Раздел «Управление различиями между браузерами» .
Следует отметить, что в приведенном выше коде все прослушиватели событий добавляются window
и все проходят {capture: true}
. На это есть несколько причин:
pagehide
, и pageshow
стреляют window
; visibilitychange
, freeze
и resume
запускаются document
, и focus
и blur
запускаются для соответствующих элементов DOM.На диаграмме в начале этой статьи показано состояние и поток событий в соответствии с API жизненного цикла страницы. Но поскольку этот API был только что представлен, новые события и API DOM реализованы не во всех браузерах.
Более того, события, реализованные сегодня во всех браузерах, не реализованы последовательно. Например:
blur
событие при переключении вкладок. Это означает (вопреки диаграмме и таблицам выше) страница может перейти из активного состояния в hidden , не пройдя сначала passive.freeze
и resume
событие, хотя это состояние все еще можно наблюдать с помощью pagehide
и pageshow
событий.visibilitychange
событие не реализовано .pagehide
и visibilitychange
событий изменились . Раньше браузеры отправляли сообщения visibilitychange
после pagehide
того, как состояние видимости страницы было видимым, когда страница выгружалась. Новые версии Chrome будут отправлены visibilitychange
раньше pagehide
, независимо от состояния видимости документа во время выгрузки.pagehide
или visibilitychange
события при закрытии вкладки (WebKit ошибки: 151610 и 151234 ), поэтому в Safari вам , возможно , потребуется также слушать beforeunload
события для того , чтобы обнаружить изменения в hidden состоянии. Но поскольку beforeunload
событие можно отменить, вам нужно подождать, пока событие не закончит распространение, чтобы узнать, изменилось ли состояние на hidden . Важно : использовать beforeunload
событие таким образом следует только в Safari, так как использование этого события в других браузерах может снизить производительность. Подробности см. В разделе устаревших API .Чтобы разработчикам было легче справляться с этими несоответствиями между браузерами и сосредоточиться исключительно на соблюдении рекомендаций и передовых методов состояния жизненного цикла , мы выпустили PageLifecycle.js , библиотеку JavaScript для наблюдения за изменениями состояния API жизненного цикла страницы.
PageLifecycle.js нормализует кроссбраузерные различия в порядке запуска событий, так что изменения состояния всегда происходят точно так, как указано в диаграмме и таблицах в этой статье (и делают это во всех браузерах).
Разработчикам важно как понимать состояния жизненного цикла страницы, так и знать, как наблюдать за ними в коде, потому что тип работы, которую вы должны (и не должны) выполнять, во многом зависит от того, в каком состоянии находится ваша страница.
Например, явно не имеет смысла отображать временное уведомление для пользователя, если страница находится в hidden состоянии. Хотя этот пример довольно очевиден, есть и другие не столь очевидные рекомендации, которые стоит перечислить.
State | Рекомендации разработчиков |
---|---|
Active |
Активное состояние является наиболее критическим моментом для пользователя и , таким образом , наиболее важное время для вашей страницы будет реагировать на ввод данных пользователя . Любая работа, не связанная с пользовательским интерфейсом, которая может блокировать основной поток, должна быть переведена на периоды простоя или передана веб- исполнителю . |
Passive |
В passive состоянии пользователь не взаимодействует со страницей, но все равно видит ее. Это означает, что обновления пользовательского интерфейса и анимация должны быть плавными, но время появления этих обновлений менее критично. Когда страница меняется с активной на passive, самое время сохранить несохраненное состояние приложения. |
Hidden |
Когда страница меняется с passive на hidden , возможно, пользователь не будет с ней взаимодействовать снова, пока она не будет перезагружена. Переход к hidden также часто последнее изменение состояния , что это надежно наблюдаемым разработчики (это особенно актуально на мобильном телефоне, так как пользователи могут закрывать вкладки или само приложение браузера, а также Это означает, что вы должны рассматривать hidden состояние как вероятный конец сеанса пользователя. Другими словами, сохранять любое несохраненное состояние приложения и отправлять все неотправленные аналитические данные. Вам также следует прекратить делать обновления пользовательского интерфейса (поскольку они не будут видны пользователю), и вы должны остановить любые задачи, которые пользователь не хотел бы запускать в фоновом режиме. |
Frozen |
В Frozen состоянии замораживаемые задачи в очередях задач приостанавливаются до тех пор, пока страница не разморозится, что может никогда не произойти (например, если страница будет отброшена). Это означает, что когда страница изменяется с hidden на Frozen, важно, чтобы вы остановили любые таймеры или разорвали любые соединения, которые в случае блокировки могут повлиять на другие открытые вкладки в том же источнике или повлиять на способность браузера помещать страницу в Back- Прямой кэш .
В частности, важно, чтобы вы:
Вы также должны сохранить любое динамическое состояние просмотра (например, положение прокрутки в бесконечном списке) в (или через IndexedDB ), которое вы хотели бы восстановить, если бы страница была отброшена и перезагружена позже. Если страница переходит из Frozen обратно в hidden , вы можете повторно открыть любые закрытые соединения или перезапустить любой опрос, который вы остановили, когда страница была изначально заморожена. |
Terminated |
Как правило, вам не нужно предпринимать никаких действий, когда страница переходит в Terminated состояние. Поскольку страницы, выгружаемые в результате действия пользователя, всегда проходят через hidden состояние перед переходом в состояние завершения , в hidden состоянии должна выполняться логика завершения сеанса (например, сохранение состояния приложения и предоставление отчетов для аналитики). Кроме того (как указано в рекомендациях для hidden состояния ), разработчикам очень важно понимать, что переход в завершенное состояние не может быть надежно обнаружен во многих случаях (особенно на мобильных устройствах), поэтому разработчики, которые зависят от событий завершения (например |
Discarded |
Discarded состояние не наблюдается разработчиками в то время , когда страница будет Discarded. Это связано с тем, что страницы обычно Discarded из-за ограничений ресурсов, а размораживание страницы только для того, чтобы позволить скрипту запускаться в ответ на событие сброса, в большинстве случаев просто невозможно. В результате вы должны подготовиться к возможности отмены изменения со hidden на Frozen, а затем вы можете реагировать на восстановление отклоненной страницы во время загрузки страницы, проверяя |
Ключевой момент: никогда не используйте unload
событие в современных браузерах.
Многие разработчики рассматривают unload
событие как гарантированный обратный вызов и используют его как сигнал конца сеанса для сохранения состояния и отправки аналитических данных, но делать это крайне ненадежно , особенно на мобильных устройствах! unload
Событие не срабатывает во многих типичных ситуациях разгрузочных, в том числе закрытия вкладки из вкладок переключателя на мобильном телефоне или закрытие приложения браузера из приложения переключателя.
По этой причине всегда лучше полагаться на visibilitychange
событие, чтобы определить, когда сеанс заканчивается, и рассматривать hidden состояние как последнее надежное время для сохранения данных приложения и пользователя .
Более того, простое присутствие зарегистрированного unload
обработчика событий (с помощью любого onunload
или addEventListener()
) может помешать браузерам помещать страницы в кэш обратного направления для более быстрой загрузки вперед и назад.
Во всех современных браузерах (включая IE11) рекомендуется всегда использовать pagehide
событие для обнаружения возможных выгрузок страницы (также известного как завершенное состояние), а не unload
событие. Если вам нужна поддержка Internet Explorer версии 10 и ниже, вы должны определить pagehide
событие и использовать его только в том unload
случае, если браузер не поддерживает pagehide
:
const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';
addEventListener(terminationEvent, (event) => {
// Note: if the browser is able to cache the page, `event.persisted`
// is `true`, and the state is frozen rather than terminated.
}, {capture: true});
Для получения дополнительной информации о обратном кэшировании и о том, почему событие выгрузки вредит им,
Прежде чем понять, как оптимизировать веб-сайты и приложения для эффективного рендеринга, важно понять, что на самом деле происходит в браузере между кодом, который вы пишете, и пикселями, отображаемыми на экране.
Для этого браузер выполняет шесть различных задач:
Иногда вы можете услышать термин «растеризация», используемый в сочетании с рисованием. Это потому, что рисование на самом деле представляет собой две задачи: 1) создание списка вызовов отрисовки и 2) заполнение пикселей. Последнее называется «растеризацией», поэтому всякий раз, когда вы видите записи рисования в DevTools, вы должны думать об этом как о включении растеризации.
60 кадров в секунду = 16 мс / кадр, но на самом деле у вас есть только 10–12 мс на выполнение всей работы из-за накладных расходов браузера.
Рисование - это процесс, с помощью которого браузер берет свою абстрактную коллекцию элементов со всеми их свойствами и фактически вычисляет пиксели для рисования. Это включает в себя вычисление стилей, таких как тени и градиенты блоков, а также изменение размеров изображений. Перерисовка происходит, когда в оболочку элементов вносятся изменения, которые изменяют видимость, но не влияют на ее макет. Примеры этого включают контур, видимость или цвет фона. Согласно Opera, перерисовка обходится дорого, потому что браузер должен проверять видимость всех других узлов в дереве DOM.
Перекомпоновка еще более критична для производительности, потому что она включает изменения, влияющие на макет части страницы (или всей страницы). Перекомпоновка элемента вызывает последующую перекомпоновку всех дочерних элементов и элементов-предков, а также любых элементов, следующих за ним в DOM. Согласно Opera, большинство перекомпоновок по существу вызывают перерисовку страницы.
К сожалению, много чего. Среди них некоторые, которые особенно важны при написании CSS:
Для полного списка проверьте суть Пола Айриша
transform: translatez(o);
will-change: transform;
Надеюсь, эта статья была вам полезной, и теперь вы понимаете, как работает Event Loop, и что 'творится' в примерах кода выше.
Исследование, описанное в статье про event loop, подчеркивает ее значимость в современном мире. Надеюсь, что теперь ты понял что такое event loop, javascript, web api, цикл событий, page lifecycle api и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Ответы на вопросы для самопроверки пишите в комментариях, мы проверим, или же задавайте свой вопрос по данной теме.
Комментарии
Оставить комментарий
Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)