Getting the transcript
Reading the captions from YouTube. A video nobody has opened here before takes 10 to 30 seconds; this page fills in on its own.
Getting the transcript
Reading the captions from YouTube. A video nobody has opened here before takes 10 to 30 seconds; this page fills in on its own.

Ulbi TV · @UlbiTV
Where viewers went back to watch this video again, from YouTube's public Most replayed graph, lined up with what was said at that moment.
Words
10,636
Runtime
1:14:29
Speaking pace
143wpm
Reading time
44min
143 words per minute, below the 160 25th percentile of 349 measured videos. That distribution comes from the 349-video hook study.
Opening (first 30 seconds)
Приветствую вас друзья в самом подробном ролике который Вы только можете найти по эвентлуп по устройству браузера по стадиям рендера про устройство node.js тем в этом ролике разберем крайне много Я думаю он будет полезен Не только начинающим но и ребятам которые работают JavaScript уже достаточное время я постарался сделать прям полноценную лекцию с приятным визуалом интересную и я надеюсь ты мои старания оценишь поставишь лайк напишешь комментарий для лучшего продвижения роликом
72 words, the words spoken in the first 30 seconds at 143 words per minute.
Free, no signup. See how the first 30 seconds hold attention, with rewrites.
What this transcript is
Every word below is the caption track YouTube publishes for this video, pulled from the video itself and reproduced unchanged. It is not Prepublish's writing, not a summary, and not a re-transcription: it is the video's own published captions. Russian captions, generated automatically by YouTube, in the video’s original language. Source: the video on YouTube. A channel that would rather this page did not exist can ask for its removal through the contact page, and it is removed.
Приветствую вас друзья в самом подробном ролике который Вы только можете найти по эвентлуп по устройству браузера по стадиям рендера про устройство node.js тем в этом ролике разберем крайне много Я думаю он будет полезен Не только начинающим но и ребятам которые работают JavaScript уже достаточное время я постарался сделать прям полноценную лекцию с приятным визуалом интересную и я надеюсь ты мои старания оценишь поставишь лайк напишешь комментарий для лучшего продвижения роликом но не будем введение сильно затягивать сразу приступим начнем с плана на урок и сразу обговорю что план этот не полный и он не отражает порядок информации Это скорее такая вводная информация которая показывает что вообще в этом уроке в этой лекции будет чтобы посмотреть прям последовательность тем и выбрать то что вам нужно можете перейти в тайм-коды которые в описании под этим видео и так в этом Сегодня мы разберем Что такое Event loop цикл событий прям подробненько по нему пройдемся сравним браузерный Event loop с Event loop который используется в not JS проговорим ПРО однопоточный многопоточную модель поговорим про движки JavaScript разберем устройство браузера то как он устроен Какие технологии внутри себя содержит Какие задачи они решают разберем основные концепции went loop опять же как я уже сказал сравним с not JS разберем Из чего состоит но Джес поговорим про Диму мультиплексор событий шаблон реактор в общем такой полезной теоретической информации в этом видео будет много и давайте начнем начнем с архитектуры браузера и плавно перейдем к Event loop Начнем с того из чего каждый браузер состоит скажем так базовая схема архитектуры любого браузера давайте начнем с того что пройдемся по каждой части Итак юзер интерфейс здесь я думаю объяснять особо не нужно это часть браузера с которой мы взаимодействуем как правило Верхняя или какая-то боковая панель это пространство где мы вводим URL нажимаем на кнопки вперед назад где различные настройки и все С чем мы в принципе взаимодействуем через UI далее еще одна составная часть браузера Это непосредственно сам браузерный движок это такая соединительная часть между пользовательским интерфейсом и механизмом рендеринга на основе входных данных от пользователя он взаимодействует с этим механизмом рендеринга и управляет им и самое наверное важная часть в любом браузере это движок рендера благодаря которому и получаем те самые заветные страницы приложения с которыми Мы в браузере уже можем взаимодействовать два самых популярных таких движка думаю вы они слышали Это веб-кит который используется в Chrome и гекко который используется Firefox И основная задача этого движка как раз обработка того кода который вы написали HTML CSS и непосредственно JavaScript строится дом дерево откроется объектная модель CSS дерева определяется расположение элементов в общем проходит определенные стадии о которых мы будем говорить позже стадии рендера как раз и после всех этих стадий мы уже видим Ту самую заветную страницу в браузере далее идут также важные части Давайте слева направо их рассмотрим первое думаю Понятно из названия предназначена для работы с сетью она отвечает за историю сайтов которые вы посещали за доменные имена за взаимодействие с ДНС сервером за за правило обработки различных доменов httphtps открытие tcp соединение взаимодействие по udp В общем все что связано с сетью обмен пакетами и так далее Далее идет движок JavaScript Это непосредственно та часть которая обрабатывает наш JavaScript код Я думаю все вы слышали про самый популярный движок который называется V8 этот движок поверх которого построен но Джес ходе которого построен Google Chrome и здесь сразу же Обратите внимание то есть у нас движок который обрабатывает JavaScript используется и на платформе node.js которая позволяет нам писать серверный или десктопные приложения и также этот же движок используется в браузере То есть это независимое абстрагированная вообще от чего-либо технология которая позволяет всего лишь обрабатывать JavaScript код про движок javascrip там еще отдельно будем говорить но если кратко он предоставляет хип так называемую кучу область памяти Где хранятся всякие объекты массивы функции и так далее стек вызовов так называемый Call Stack он предоставляет работу с памятью выделения сборка мусора Ну и самое главное задача это конечно же компиляция Java скрипта в машинный код и остается у нас последняя часть из нарисованных сейчас на слайде это юань Back and это наверное как разработчиков сторонних нас интересует меньше всего Это какая-то внутренняя часть которая предоставляет какую-то логику для Вот как раз Интер процесса самого браузера то есть какая-то логика подкапотная и остается последняя часть архитектуры браузера это определенное хранилище данных это Local storage это Session storage это idb webesql файловая система если нам например там картинку какую-то в браузер загрузить надо в общем это такое хранилище которое использует браузер также он обрабатывает куки работу со вкладками хранит их в памяти это все хранится локально скажем так локальная база данных в общем Сейчас мы рассмотрели грубо говоря такой шаблон любого браузера Я предлагаю посмотреть на конкретную имплементацию на примере Google Chrome Здесь вы можете заметить как раз все те части которые мы рассматривали но нас как разработчиков как фронтенд разработчиков По большей части интересует движок рендера и движок JavaScript Как видите в качестве движка рендера здесь используется веб-кит в качестве движка JavaScript используется V8 Это тот же самый напомню что используется под капотом в not.js здесь у нас еще появляется партир xml появляются плагины стек каких-то инструментов для взаимодействия с сетью Ну и в целом вот так вот выглядит архитектура хрома на самом деле собрать свой браузер не так уж и сложно По большей части все вот эти браузеры они состоят из Open Source технологий эти опенсорные технологии просто необходимо объединить Итак с архитектурой браузера в таком базовом варианте мы познакомились Давайте посмотрим теперь Из чего состоит архитектура движка рендера рассмотрим на примере самого популярного этого кит то есть на вход в него приходит HTML CSS он парсит HTML с помощью специального парсера парсит CSS с помощью другого специального парсера на выходе первого у нас получается дом дерева с которым через JavaScript мы уже работаем на выходе второго получаются определенные правила правило стилей по итогу строится дерево это рендера это Ключевое дерево за счет которого мы видим элементы на странице и потом проходят определенные стадии layout Painting composit и Вуаля страница рендерится и мы можем с ней взаимодействовать про вот эти стадии я буду подробнее рассказывать в соответствующем разделе пока что просто воспримем как факт что эти стадии есть то есть тоже какой-то магии здесь прям Нет все подчиняется строго определенным правилам Итак на архитектуру Хрома и движка рендера webkit мы глянули Давайте теперь просто для сравнения посмотрим на архитектуру Firefox Как вы можете заметить здесь у нас используется абсолютно все те же части браузер Engine рендеринга Jean JavaScript интерпретатор инструменты для работы с сетью но как вы можете тоже заметить что здесь используются другие имплементации То есть если для партинга JavaScript кроме использовался V8 то здесь используется совсем другой движок он называется Spider Monkey если говорить про движок рендера то здесь используется гекко к слову браузеров намного больше чем те о которых мы знаем их сотни различных причем в разных странах популярные разные браузеры Ну в принципе это логично и стоит заметить что во многом эти браузеры используют одни и те же инструменты но если мы возьмем основные такие как Firefox Opera Google Chrome и Safari то там под капотом как правило используются разные инструменты про архитектуру продвижки мы на самом деле говорили не зря это в дальнейшем пригодится Сейчас самое важное понимать что Event loop не является частью Java скрипта потому что у многих начинающих такое понимание что вот этот эвентлуб он как бы всегда идет рядом с Java скриптом на самом деле нет и в доказательство этого можно сказать что в Хроме используется V8 движок для обработки Java скрипта в not JS используется также V8 но при этом even Club в браузере и эвентус в not.js это абсолютно разные концепции но в целом решают они одну задачу но реализованы они по-разному Итого Event loop это отдельный механизм который позволяет использовать не блокирующую модель ввода и вывода Давайте поймем что это такое представим себе ситуацию что у нас нет никакой асинхронщины нет никакого вент-лупа мы вот так Шаг за шагом выполняем строчку за строчкой нашего JavaScript кода но возникает вопрос Что делать если мы хотим Вот это выполнение кода как-то раз параллелить например одновременно отправить запрос нажимать на кнопку вводить что-то в Input и при этом чтобы у нас анимация на странице работала и чтобы не получилось так что мы отправили запрос на сервер и у нас весь код заблокировался потому что нам важно дождаться ответа от этого сервера то есть еще раз задача как-то чтение и выполнение этого кода раз параллелить чтобы отправка запроса нажатие на кнопку вот чего-то вымпуд не блокировала весь остальной код чтобы анимация могла там работать где-то Независимо обработка нажатия кнопки была Независимо но думаю основную идею вы поняли и вот для этого как раз Event Club цикл событий и предназначен И сейчас мы шаг за шагом будем разбираться как он работает Итак давайте начнем есть Так вызовов за его обработку отвечает как раз движок Джава скрипта Ну представим что это Например V8 стек это определенная структура данных хранилище которое можно представить виде стопки бумаг Если мы хотим бумагу взять мы ее берем сверху в топке А если мы хотим бумагу в эту стопку добавить то мы складываем ее также наверх И вот кол-стек стык вызовов вот так вот как бумагу складывает функции в определенном порядке в том в котором они должны быть вызваны и сейчас поэтапно Шаг за шагом начиная с самых простых примеров мы будем разбираться как это все работает и какое место в этом всем имеет Event loop здесь код максимально простой и в принципе здесь никакой магии нет Мы выполняем одну функцию выполняем вторую функцию То есть она попадает в стек и сразу же из него выходит и третья функция также попадает стек сразу же из него выходит и выполняется то здесь код простой функции выполняются одна за другой Давайте посмотрим пример чуть посложнее здесь функции вложены друг друга Мы выполняем третью функцию внутри нее содержится вызов второй функции а внутри нее содержится вызов первой функции и вот теперь они поочередно начиная сверху начинают вот так выходить то есть выполняется первая функция потом вторая и только третье это как раз аналогия с той самой стопкой бумаг так работает стек здесь пример уже чуточку посложнее здесь у нас рекурсия Обратите внимание что функция факториал внутри себя вызывает другую функцию факториал при этом есть базовый случай который позволяет Вот эту вот петлю рекурсивную закрыть Давайте посмотрим как будет заполняться стек вызовов в таком случае мы вызываем факториал с пятеркой затем вызываем с четверкой стройкой вызываем с двойкой и вызываем с единичкой при этом здесь у нас на базовом случае рекурсия завершается и мы начинаем вот в таком порядке эти функции выполнять начиная с единички и так до пятерки и в итоге мы получаем нужный нам результат но есть один очень важный нюанс вот этот вот самый колл-стек он не бесконечный то есть при определенных условиях его можно переполнить и приложение У нас крашнется например если мы вызовем факториал с очень большим числом у нас Call Stack переполнится и приложение выстрелит ошибкой То есть он по количеству находимых в нем функций ограничен Именно поэтому на собеседованиях любят дать какую-нибудь рекурсивную задачку и потом спросить а что же будет если мы передадим туда например вот очень большое число а потом еще и спросят как это можно переписать например обход дерева какой-нибудь через стек или Решение вот такой вот рекурсивной задачки через обычный цикл то есть чтобы здесь не было переполнения стыка вызовов мы могли решить эту задачу с помощью вот такого вот обычного цикла перебором Да мы в результате получили бесконечность потому что JavaScript с такими большими числами работать не умеет но приложение при этом у нас не крашнулось бы примеры которые мы рассматривали ранее являются синхронными то есть код выполняется строго в определенном порядке Шаг за шагом Но что если мы хотим отложено например через три секунды выполнить какое-нибудь действие например показать пользователю сообщение о том что он провел на нашем сайте пять минут Давайте посмотрим на пример кода То есть у нас есть Лок Старт Lock and и посередине у нас сайт тайм-аут который выполнится через три секунды и давайте рассмотрим Как с точки зрения эвент лупа этот код должен выполняться Event Club содержит внутри себя очередь это очередь называется очередь задач то есть порядок выполнения кода здесь будет такой у нас выведется Лок Старт Lock and и только потом тайм-аут в принципе все логично у нас попадает Лог в колл-стек затем у нас туда попадает сет тайм-аут но callback который мы Передаем внутрь тот самый хендлер в котором выводится тайм-аут он не выполняется сразу то есть он не попадает в этот колстек он попадает в ту самую очередь задач То есть это вот в нашем случае анонимная Стрелочная Функция которую мы передали внутрь сеть тайм-аут Она остается в этой очереди и находится там то есть мы ее грубо говоря запомнили и зарегистрировали Как происходит регистрация поговорим позже позже потом у нас выполняется Lock and и только после того как у нас прошли три секунды у нас выполняется вот эта Стрелочная функция и внутри нее выполняется Лок тайм-аут и вот здесь очень важный момент что задачи из очереди могут попасть в стек только после того когда этот стек полностью очистится То есть все функции должны выполнится стек у нас пустой и только тогда мы можем взять что-то из очереди и выполнить Это очень важный момент если пока не понятно то дальше будет больше примеров и вы обязательно разберетесь и сейчас может возникнуть вполне резонный вопрос как вот эти вот задачи попадают в ту саму очередь как мы уже выяснили за очередь отвечает Event loop А за колл-стек у нас отвечает движок JavaScript это может быть в 8 чакра Spider Monkey или JavaScript Core он используется в сафари то есть еще раз давайте обговорим Какие задачи решает JavaScript движок А какие зада не мешает Event loop движок JavaScript решает следующие 4 основные задачи во-первых Это работа с кучей так называемых хип и стеком вызовов это вот тот самый колл-стек Это работа с памятью выделение памяти и сбор мусора в принципе вот эти вот все движки они для любых других языков программирования работают примерно похожим образом самое главное задача движка как я уже говорил это компиляция JavaScript машинный код Ну и также движок отвечает за различные компиляции скрытые они внутренние уже это всякие каши скрытые классы и так далее там достаточно такие точечные оптимизации сложные Как это работает уже вдаваться наверно нам не стоит поскольку мы не являемся разработчиками компиляторов и вот здесь важно понимать уже наверное 4 или 5 раз об этом говорю но я не зря на этом останавливаю внимание клуб не является частью движков Эван клуб предоставляется средой это может быть но Джес или какая-либо другая среда разработки в которой эвентлуп требуется при этом также повторю устройство Event loopa может быть разное еще тоже в 10 раз повторю чтобы уже точно начинающий запомнили в Хроме у нас используется V8 в No JS у нас используется V8 Однако устройство цикла событий в них разное и когда мы будем разбирать not JS в конце этого ролика вы в этом Убедитесь Итого вернемся к вопросу если у нас движок JavaScript предоставляет Call стек а очередь задач предоставляет even Club как они общаются между собой и здесь на самом деле все тоже крайне просто никакой магии нет у каждого браузера есть веб API это API предоставляет как раз всякий тайм-аут и обработку слушателей события нажатия на кнопки различные события загрузки изображений файлов отправку каких-нибудь запросов То есть это все не спецификация Java Да это всё исключительно браузерные штуки и вот Давайте тот же самый пример рассмотрим но теперь с участием веб-апе точно также сет тайм-аут у нас попадает в колл-стек после этого он регистрируется в API и вот на этом этапе запускается таймер после того как таймер иссяк мы отправляем наш калбек в очередь задач и он после того как колстек очистился когда настало время взять задачу из очереди он выполняется то есть порядок такой выполнились все синхронные задачи После истечения таймера задача попадает в очередь и после того как все синхронные задачи выполнены Мы берем задачи из этой очереди и выполняем ее отлично сет тайм-аутом думаю Понятно теперь давайте посмотрим похоже пример носа слушателем события точно так же у нас это Event listener попадает в Call Stack выполняется после чего в API регистрируют слушатель события на кнопку то же самое происходит с второй кнопкой Web API события регистрируют и мы знаем что эти события у нас зарегистрированы при этом интерфейс у нас не блокируется и после того как мы нажмем на эти кнопки на интерфейсе у нас также генерируется таска в очередь задач и после того как выполнились все синхронные задачи из колл-стека у нас это таска выполняется То есть за счет вот этой асинхронной модели мы можем иметь одновременно в нашем приложении тысячи слушателей события на кнопки Input и Select и дроп дауны В общем на все что нам нужно мы имеем эти слушатели события они вот таком асинхронном режиме выполняются при этом эти слушатели события будут зарегистрированы пока мы их явно не удалим через Remove and lissaner то есть опять же вот эти все кнопки события это не спецификация Java скрипта это исключительно браузерная часть браузерная веб API Я думаю все разработчики frontend слышали что раньше лет 10 назад была большая проблема что в каждом браузере код работал по-разному была проблема с поддержкой Internet Explorer сейчас иногда возникают проблемы при поддержке Сафари это как раз связано с тем что отчасти браузеры работают по-разному несмотря на то что все вот эти браузеры пытаются стандартизировать сделать так чтобы они работали похожим образом все равно вот такие вот нюансы различия иногда всплывают отлично с этим разобрались двигаемся теперь дальше представим себе ситуацию что у нас в коде появляется еще промис подразумевается что люди которые это видео смотрят они знают что это такое и того мы знаем что с помощью промиса Мы также можем запускать какой-то асинхронный код который не будет блокировать основной поток например браузерный фетч для получения каких-то данных работает именно на промисах но как вы можете заметить сет тайм-аут у нас в качестве тайм-аута передано 0 миллисекунд и возникает вопрос Что запустится быстрее промисс либо же с этой Ну и немного заспойлерю порядок будет таким сначала выполнить солод 1 затем Lock 4 затем выполнится Лог 3 в промесе и только потом выполнится Lock 2 и возникает вопрос как вот этот Event loop понимает Какие задачи брать ему быстрее промисы таймауты калбеки из например какой-нибудь подгрузки файла слушатели событий и так далее И на самом деле когда я рассказывал про очередь задач Я немного не договорил на самом деле этих очередей две это очередь событий или же очередь макро задач и очередь задач либо же очередь микрозадач как их по-другому в разных источниках называют так вот у этих очередей есть определенный приоритет и Event loop берет задачи таски в определенном порядке и Давайте разберемся как это все работает на детальных примерах сейчас мы видим что в попи зарегистрировала сайт тайм-аут промесь На текущий момент находится у нас в колл-стеке и вот здесь важный момент промисы всегда попадают в очередь микро тасок всегда это очень важно запомнить Потому что от этого зависит то как будет выполняться ваш код буквально совсем недавно мне на собеседовании задали вопрос с реальным багом который у ребят в компании возник в проде и это было как раз связано вот этими очередями и того промис у нас попал в очередь микро задач затем у нас выполняется Lock 4 и на текущем этапе у нас все синхронные задачи выполнены то есть Call Stack у нас пустой вот здесь как мы выяснили раньше начинает как раз работать Event loop и забирать вот эти задачи из очередей плюс ко всему в какой-то момент нулевой тайм-аут у нас выполняется в баке его обрабатывает и перемещает вот этот колбек который находится внутри таймаута как раз макро таск очередь в очередь событий и вот здесь как раз возникает вопрос что будет выполнено быстрее тайм-аут или же промес но мы уже выяснили что порядок у нас будет 1432 то есть промес отработает быстрее и это как раз специфика работы эвентлупа в приоритете в первую очередь всегда выполняются микро таски причем сразу все и только потом выполняется одна макро таска позже на примере мы это разберем смотрим на слайды То есть у нас сейчас выполняется Лог 3 из промиса и только потом у нас выполняется Лог 2 который находится в сет тайм-аут то здесь отработала макро таска то есть простейшем случае с одним промисом и с одним тайм-аутом с одной микро таской с одной макро-таской порядок выполнения программы будет Именно таким выполняются синхронные выполняются микро таски и выполняется макро-таска теперь предлагаю рассмотреть пример когда у нас несколько макро тасок и несколько микро тасок как в этом случае будет эти задачи обрабатывать здесь на самом деле все будет так как я и сказал он по очереди выполнит все микро таски одну за одной и после того как очередь микрозадач освободилась когда она стала пустой когда все задачи из нее были выполнены берется одна задача из очереди макро тасок Причем я не зря акцентирую внимание на том что берется Именно одна задача Давайте представим что у нас там какой-нибудь сет тайм-аут который внутри себя выполняет например запрос Федя запрос это тоже промес такое Ну в принципе очень часто бывает по какому-то интервалу по какому-то тайм-ауту Мы например чем какие-нибудь данные То есть у нас получается так что у нас макрозадача порождает микрозадачу промис внутри себя и вот здесь Обратите внимание макро таск под номером 2 у нас не выполняется у нас выполнится Сперва Micro Task который породился макротаском и только потом у нас Event loop забирает задачу из очереди в макро задач вторую задачу давайте сейчас уже без моих комментариев посмотрим на работу этой Схемы еще раз достаточно важный момент поэтому подытожим еще раз сначала выполняются все синхронные задачи потом выполняются все микро таски выполняется 1 макро таска если она порождает другие микро тоски то выполняются Опять они все сразу потом выполняется вторая макро таска и так по кругу одна макро таска все микро таски одна макро таска все микро таски с порядком выполнения на таких примерах думаю всем должно быть Понятно Как это работает но Давайте теперь разберемся что такое микро таски А что такое макро таски и так как мы уже выяснили микро тоски на 99 процентов это всегда промисы то есть по большей части код который Вы пишете порождать микро таски будет только через промеси но также Если вдруг возникла какая-то необходимость эту микро тоску можно Как создать явно с помощью функции Q Micro Task чуть позже мы на реальном коде на реальных примерах тоже посмотрим как это работает и убедимся что действительно промисы и микро таски которые мы создаем через эту функцию это по сути одно и то же попадают эти задачи в одну очередь и также микро таски еще порождает мутейшен обервер это специальный инструмент который позволяет следить за дом нодами чуть позже мы его также опробуем кстати Об этом я сам узнал недавно на одном из собеседований ссылка на который сейчас всплывет в подсказке Итого Мы выяснили что микротоки на 99 процентов это всегда промисы а что же такое тогда макро таски это как раз таймеры сет тайм-аут интервал события загрузка изображения Клик вот чего-то в Input и всякое такое и плюс браузерные нюансы иногда это может быть рендер какой-то Input output вот вывод и все что вот браузерная скажем так подкапотная то есть ничего сложного нет никакой магии нет стоит это запомнить понять В какой очередности выполняются те или иные задачи и в принципе базовое понимание эвентлупа У вас есть Повторение мать учения допускаю что этот ролик будут смотреть совсем начинающие поэтому Давайте закрепим Итого выполняются синхронные задачи из call-stake затем even Club обрабатывает все таски которые находятся в очереди задач в микро тоскую затем выполняется одна макро таска и вот в таком вот режиме цикл крутится И вот так вот 123123 задачи выполняет одну за одной рисунки слайды анимация это все хорошо но хочется реального кода Давайте его разберем здесь принципе похоже все на то что мы делаем у нас есть вот такой тайм-аут который выводит себе синхронный Лог и промес в котором тоже выводится Лог затем идет другой сайт тайм-аут другой промис и еще один промез То есть вот такой вот порядок у нас большого количества микро и макро тасок сейчас рекомендую поставить на паузу выписать порядок консоль логов и затем Запустить видео также обращу внимание что сейчас я буду запускать этот код в node.js но при этом для Вот таких простых примеров это будет работать точно так же как и в браузере Итого 1 2 3 код запускаю и смотрим на пример выполнения и порядок у нас такой 14 это логично это у нас синхронный консоль логи далее 20 тайм-аута у нас пропускаются и в конце логах у нас идет про Мис 1 и про Мис 2 то есть выполнились микро таски затем у нас выполняется сет тайм-аут 1 вот этот вот тайм-аут в нем выполняется вот этот консоль Лог и Обратите внимание у нас дальше не выполняется сет тайм-аут 2 у нас сначала выполняется вложенный в первый сет тайм-аут промис то есть выполняется микро таска и только после того как очередь микро тасок очищена у нас выполняется последний сет тайм-аут под вторым номером Несмотря на то что мы передали даже туда нулевой тайм-аут и вот в таком вот цикле в цикле события это все работает Давайте Теперь попробуем Добавить сюда еще вызова вот этой вот самой функции Q Micro Task и убедимся что порядок У нас тоже сохранится это вот такая вот функция которая принимает callback в принципе похоже на промез образом она работает и передадим внутрь Micro Task 1 Давайте даже сделаем два и куда-нибудь сюда в начало вставим еще с единичкой чтобы убедиться что порядок правильный запускаем Еще раз Ну и видим что у нас выполнилось начало микро ТАСС 1 затем промисс потом Micro tast 2 и опять промес Ну и остальные логи у нас без изменений то есть мы убедились что промисы и вот эта функция Q Micro Task работают с одной и той же очереди Ну и Давайте еще убедимся что микротоски выполняются все сразу после того как выполнилась одна макро таска то есть здесь Давайте еще добавим сет тайм-аут можно еще номера поменять ну и да видим что перед вызовом второго с этой маута у нас выполняются все микро таски то есть в таком вот режиме это все работает макро таска все микро таски затем опять макро таска если она порождает микро таски то будут выполняться они также мы выяснили что помимо qi микро Task и промисов вот эти вот самые Micro tasky создает еще mutation Observer для общего развития давайте тоже посмотрим что он из себя представляет для лучшего понимания сразу рассмотрим на примере у нас есть вот такая простенькая html-ка в которой есть заголовок и кнопка которая в этом заголовке увеличивает на единичку счетчик 0 1 2 3 в общем обычно инкрементация так вот теперь Давайте попробуем воспользоваться мутейший над зервером если кратко то это специальный механизм который позволяет следить за изменениями в дом Как видите в него передается вот такой калбек и в нем есть вот такой вот mutation Record здесь можно следить за добавленными нотами за какими-то предыдущими значениями за удаленными нотами То есть можно следить за манипуляциями которые происходили с нодами чтобы получше понять как эти мутации выглядят Давайте выведем их влоги и также помимо создания самого мутейшина джофера ему необходимо сказать зачем мы будем следить не указываем что следить мы будем за хедером Также можно передать опции в которых можно указать атрибуты за которыми Мы хотим следить можно указать хотим ли мы следить за под деревом хотим ли мы следить за предыдущим значением общем Здесь целый ряд каких-то атрибутов и их тоже можно настраивать открываем консольку нажимаем на кнопку и видим как у нас логах появляются вот эти самые mutation Record если мы зайдем то мы увидим что здесь у нас есть как раз все необходимые данные можем проследить какие ноды были добавлены Видите вот это надо типа текст то здесь у нас в качестве дата передана была четверка Ну и на основании этих данных мы можем производить тоже какие-то манипуляции следить за изменением того или иного элемента Давайте попробуем теперь не заменять HTML внутри самого аккаунта а попробуем добавить у него какую-нибудь ноду с помощью openchild с помощью Great элемент создадим какой дивчик Ну и в принципе наполнять его ничем не будем как есть передадим обновим страницу по нажимаем на кнопку Как видим теперь motation Record У нас две записи то есть дважды объект был изменен ну и мы видим что у нас добавилась новая нода это у нас уже не просто текст а это уже непосредственно Диф вообще зашли мы сюда не смотреть за тем как работает mutation обзор Мы зашли Изучить механизм-клупа и вот как нам теперь понять что mutation Observer действительно генерирует микро таски и сделать это максимально просто прям внутри эвент листинера Давайте выведем логи сразу после того как мы поменяли дом ноду напишем автор change потом сделаем промез resolve Здесь тоже мы видим что-нибудь консоль логи и также добавим еще с этой тайм-аут если mutation Observer действительно генерирует микротоску то мы увидим ее перед выполнением промысле золов то есть после автор чейндж мы влогах должны получить список наших мутаций вот этот самый и только потом мы должны получить сайт тайм-аут думаю концепция понятна Теперь давайте вернемся в браузер и в этом убедимся нажимаем на кнопку Ну и да получаем сначала синхронный консоль потом получаем записи mutation Record потом Promise и только потом таймер из этого можно сделать вывод что действительно после изменения какой-то дом ноды у нас motation сервер стреляет микро тосками в общем с микро и макрозадачами я думаю мы рассмотрели уже достаточное количество примеров и всем должно быть Понятно Но если по какой-то причине непонятно отматываете и пересматриваете и пробуйте экспериментировать сами но Мы двигаемся дальше и сейчас думаю подходящий момент рассмотреть то как браузер отрисовывает непосредственно ту страницу с которой мы взаимодействуем в браузере и в какой очередности по каким стадиям вот этот весь процесс происходит это на самом деле тоже интересно важно понимать хотя бы как минимум для общего развития Итак первая стадия называется калькуляция стилей На этом этапе браузер применяет вот те самые селекторы которые мы пишем непосредственно к элементам То есть он по этим селекторам проходится и определяет Какие стили и к чему необходимо применить тут важно понимать что для одного и того же элемента на странице могут быть применены разные селекторы в разных файлах с разными стилями и вот это все надо подсчитать поэтому этапы называется калькуляция стилей и уже понять почему и что мы применяем и вот здесь тоже важно понимать чем сложнее у вас селектор если у вас там есть какие-то вложенности почет каких-то и вот чем больше Вот таких вот селекторов тем конечно же почитать эти стили сложнее и тем больше нагрузка на ваше железо понятно что в современном мире упарываться в какую-то оптимизацию на данном моменте не стоит Но опять же важно в голове держать что Чем проще у вас селекторы тем быстрее у вас будет работать этот этап отлично с этапом калькуляции стилей разобрались двигаемся дальше следующий этап называется layout этот этап достаточно ресурсоемки и на этом этапе браузер уже знает какие стили К какому элементу должны быть применены за счет того что он получил на первом этапе и на этом этапе происходит уже грубо говоря составление макета чертежа нашей страницы он понимает на какую часть С какими отступами и куда необходимо разместить тот или иной элемент думаю многие из вас видели как делаются прототипы в фильме это когда без реальных цветов без реальных каких-то иконок просто делают грубо говоря позиционирование расположение каких-то элементов на странице вот браузер делает примерно то же самое он строит вот этот прототип и на выходе после этого этапа мы получаем так называемое layout 3 дерево расположение дерево позиционирование дерево макета Ну тут по-разному можно перевести на самом деле не столь важно если какой-нибудь дом дерева содержит полную информацию о каждой ноде из которой состоит наша страница то вот это лаял 3 содержит в себе информацию о том где элемент должен располагаться виден ли он не виден и так далее думаю суть основная ясна с этой стадии разобрались двигаемся дальше следующая стадия называется Paint и наверное для нас как для пользователей приложения это самое важное часть на выходе из предыдущего этапа мы имели вот этот каркас прототип и его остается в соответствии со стилями которые Вы получили на первом этапе разукрасить Я думаю вы уже заметили что каждый предыдущий этап передает какую-то новую информацию для каждого последующего и вот на текущем этапе на основании дерева которые мы получили На прошлом этапе строится так называемый Paint Records определенный записи вот этой самой отрисовки и остается последняя заключительная стадия во всем этом Flow и называется она композитин композиция здесь браузер делит то что мы получили на определенные слои и создает дерево слоев если на этапе layout у нас был layout 3 ТО на этом этапе у нас получается layer 3 в общем здесь браузер работает со слоями делает он это так чтобы у нас правильно все это обрабатывало видеокарта чтобы у нас правильно располагались элементы на странице в зависимости от индекса и так далее В общем здесь уже много всяких внутренних деталей в которых я тоже не особо Эксперт так как разработчикам браузеров я не являюсь Но вот какие-то такие на верхнеуровневые простые моменты Мы в принципе разобрали и вот сейчас может возникнуть вопрос Когда у нас строится Дом дерева Когда у нас строится дерево стилей на самом деле происходит это все чуточку раньше Как только мы получили непосредственно HTML и CSS в этот момент строится Дом CSS ом CSS object Model и непосредственно само дерево рендера а потом уже идет калькуляция стилей layout Paint и compositing при первой отрисовке работает это все именно так Но что будет если мы нажмем на какую-нибудь кнопку она вызовет какую-нибудь анимацию и при этом у нас еще откроется модальное окно то есть по сути у нас и стиле меняются и отображение элементов на странице меняется и при этом дом дерево тоже может меняться потому что у нас появляется в нем еще и мадалка и здесь по сути ничего не меняется мы нажимаем на кнопку У нас JavaScript триггерить например изменения стиля шрифта и у нас вот эти стадии идут по кругу у нас генерится новая дом дере какая-то часть его меняется меняется какая-то часть CSS object Model строится новая рендер 3 и проходят все вот эти стадии по кругу и вот здесь важно понимать что рендер это очень дорогостоящая операция ресурсов это может кушать много особенно если вы там с какой-нибудь старенького телефона это может быть ощутимо и поэтому важно стараться работать с дом нодами как можно меньше и если вы с ними работаете то надо стараться затрагивать Как можно скажем так нижней части этого дерева то есть не перерисовывать большой кусок под дерево А перерисовывать как можно меньшей это вызовет Ну как бы меньше нагрузку Если вы работаете с каким-нибудь реактом об этом По большей части думать не нужно потому что под капотом реакцион работает с виртуальным дом деревом и к манипуляциям с реальным дом деревом он приступает когда что-то действительно изменилось А вот если вы пишете на нативном JavaScript и об этом всегда стоит помнить потому что иногда бывает так Что изменяется например какой-нибудь один элемент в списке А код написан таким образом что там весь список перезатирается ради того чтобы изменить одну дом ноду и вот такого конечно же стоит избегать Теперь давайте разберемся что вообще вызывает рендер это изменение размера окна Когда вы его уменьшаете или наоборот увеличиваете изменения шрифта изменения контента что по сути одно и то же добавление или удаление новых классов или стилей манипуляций с дом деревом напрямую изменение ориентации Когда вы телефон разворачиваете в горизонтальной или вертикальное положение Когда вы меняете размер или позицию в том числе через трансформ это тоже меняет и тоже надо пересчитывать хотя это не затрагивает соседние элементы а только элемент которому эту трансформацию применяете Ну думаю это моменты так очевидные Однако стоило бы их проговорить и про эти стадии я на самом деле рассказывал тоже не зря они вот в этом всем Flow синхронно хронного кода тоже имеют свое определенное место и браузер понимает когда эти операции необходимо делать и в каком порядке то есть там какие-то свои внутренние оптимизации тоже есть это все вот так по кругу крутится выполняются таски микро таски задачи из колл-стека производится рендер и у этого всего есть определенный порядок и Однажды когда эта тема интересовался я наткнулся на конференцию в которой была очень хорошая визуализация того как это все работает в тандеме и сейчас Я позволю себе эту визуализацию добавить к себе в ролик надеюсь на меня страйки из-за этого кидать не будут и так вот она это визуализация Центральная часть это у нас синхронные задачи слева у нас расположены какие-то таски а справа непосредственно рендер первая стадия это калькуляция стиля она помечена буковкой с вторая стадия у нас была яут это соответственно буковка L и третья стадия у нас была Paint она здесь помечена буковкой п и Вот соответственно ивент лук наш Крутится крутится выполняет какие-то задачи потом в определенный момент браузер понимает что ему необходимо интерфейс обновить он открывает Вот эту вот заслонку и у нас проходят все стадии рендера то есть перерисовка при изменении каких-то визуальных частей происходит не мгновенно браузер он достаточно умный там встроенные оптимизации внутри и он понимает что накопилась какая-то порция изменений и эту порцию он перерисовывает сразу для того чтобы вот эти стадии не проходить несколько раз а вот здесь вот момент Давайте несколько раз его Посмотрим когда у нас появляется какая-то асинхронная задача у нас открывается левая заслонка и тогда браузер выполняет асинхронную задачу то есть в таком вот формате он крутится Крутится крутится выполняет синхронные задачи выполняет асинхронные задачи делает перио Надеюсь основную идею вы поняли и Давайте Немного подытожим колл-стек это часть движка JavaScript и непосредственного отношения к эвент лупу кол-стек не имеет Event loop это в случае браузера по сути две очереди макро очередь и микроочередь очереди задач как мы уже выяснили в микро тоске у нас попадают в первую очередь 98 процентов промисы во вторую очередь туда могут попадать задачи явно созданные с помощью функции Q Micro Task и в-третьих это событие которое генерирует нам mutation Observer задачи которые нам генерирует случае макро тасок это таймеры сет тайм-аут интервал это событие Клик загрузка изображения вот чего-то в Input общем все события которые мы обрабатываем и различные браузерные нюансы render Input output и так далее причем рендер как мы уже разобрались на этих стадиях там тоже своя специфика выполнения браузерная подкапотная нам это особо прямо углубляться и Не стоит так как на этом и особо повлиять никак не можем очередность выполнения как мы выяснили такая сначала выполняются все синхронные задачи из колл-стека затем выполняются все микро таски затем выполняется одна макро таска если это макро таска поражает микро тоски то тогда выполняются опять все порожденные микро таски и затем выполняется одна макро таска и так до тех пор пока все задачи не будут выполнены также мы вообще прошлись по различным стадиям рендера выяснили что у нас строится Дом дерева строится CSS object Model дерево по сути такой же как дом но связано со стилями по итогу мы получаем дерево рендера и проходим 4 стадии калькуляция стилей layout Paint и compositing опять же углубляться в это все не стоит Но хотя бы примерно понимать вот вообще понимать что это за слова что это за стадии Как зачем они выполняются и кратко понимать для чего они нужны в принципе для общего развития не помешает но Мы двигаемся дальше про браузер мы поговорили Теперь давайте поговорим про nod.js сравним это все дело поговорим про многопоточную однопоточную модель про блокирующие не блокирующий ввод вывод про различные шаблоны например реактор против мультиплексор событий про то как устроен но Джейс внутри На каких технологиях затем поговорим про Event loop который сделан там немного по-другому в отличие от того же браузера и сравним их опять же это все информация для общего развития думаю многим интересно будет такое тоже посмотреть даже фронтенд разработчикам Итак друзья поговорим о том что представляет из себя но Джес на чем Он построен и как из разработки браузерных приложений на JavaScript Мы перешли к полнофункциональной разработке на Джес каким же образом надо позволяет нам делать серверные приложения Давайте об этом поговорим пару слов о самой ноги но да Это не язык программирования но да это программная платформа с помощью специальных инструментов много позволяет превращать JavaScript в машинный код изначально JavaScript это язык разработки браузерных приложений и некоторые функциональность там очень ограничена например взаимодействовать с операционной системой мы не можем работа с файловой системой крайне ограничена так вот not JS добавляет возможность для JavaScript взаимодействовать с устройствами ввода-вывода через свой специальный API написанный на c++ и так теперь поговорим о концепциях как я уже сказал задача non.js это преобразовать Исходный код на JavaScript в машинный код подобное преобразование достигается за счет движка V8 на котором построен на Джес 8 этот движок который разрабатывает компания Google в него вливаются огромные деньги и он также используется во всеми используемым браузере Google Chrome V8 написано c++ и работает он как на винде на Маке так и на линуксе его задача скомпилировать и выполнить Исходный код на JavaScript также он занимается выде памяти для объектов и занимается сборкой мусора то есть удаляет из памяти те объекты которые Ему больше не нужны второй столб на котором основан на GS это libuv связки с V8 они образуют фундамент но JS и по сути являются основой лебеви отвечает за два принципиально важных момента первый это рост платформенный Input output то есть вот и вывод и второй момент это цикл событий так называемый Event Club уверен многие из тех кто смотрит этот курс уже частично знакомы с этой технологией но с ней мы ознакомимся еще чуть позже Давайте поговорим про каждый из этих пунктов за которые Отвечает ли Итак кроссплатформенные операции ввода и вывода К ним относятся работа с файловой системой работа сетью и на разных операционных системах это работа происходит по-разному но для того чтобы мы могли установить not JS на любой операционной системе и имели возможность работать например с файловой системой нужна оболочка некий программный интерфейс позволяющий нам это взаимодействие организовать этим как раз и занимается лебеви то есть мы через JavaScript даем команду not GS прочитать такой-то файл Или отправь какие-то данные на клиент оно Джейс Чтобы это сделать внутри себя использует эту библиотеку Levi таким образом вот это вот кроссплатформенность как раз достигается средствами libuv именно Эта библиотека знает как работать на Windows Как работать на Linux Как работать на Mac и так далее нас как разработчиков на самом деле особенно начинающих это не очень интересует но знать эту всю водную необходимо для того чтобы в дальнейшем обучение в целом шло более продуктивно чтобы вы понимали что такое not GS И что это не какой-то черный ящик А что Он построен на каких-то конкретных технологиях на каких-то конкретных платформах и они реализованы так-то так-то и так кроссплатформенный вот вывод мы обсудили теперь перейдем к циклу событий Более подробно мы о нем поговорим чуть это очень важная тема Но для общего понимания сейчас скажу пару слов во многих языках программирования в таких как сие Java Python все инструкции все команды по умолчанию являются блокирующими то есть разработчик который не позаботился об асинхронном выполнении кода заблокирует все приложения например мы пытаемся считать файл с файловой системы или же обработать какой-то сетевой запрос и так вот пока вот этот файл не считается полностью из файловой системы приложения у нас заблокируется и другие инструкции выполняться не будут для того чтобы это предотвратить используется так называемая многопоточное программирование Управление потоками или трейдами как их по-другому называют параллельное программирование это достаточно большая тема для изучения требует хорошей компетенции так вот с помощью цикла событий разработка асинхронных приложений становится гораздо проще нам не нужно заморачиваться над созданием физических потоков в этом случае когда not jess необходимо выполнить какую-то операцию ввода-вывода опять же загрузки каких-то данных из сети доступа к базе данных файловой системе вместо того чтобы на время выполнения этой операции заблокировать главный поток но Джесс просто продолжать заниматься другими делами Как раз до тех пор пока результаты выполнения этой операции не будут получены подобные махинации происходят в цикле цикле событий Почему в цикле событий вы узнаете чуть позже когда мы будем говорить про событийно-ориентированную модель на которой построен как раз но Джес Итак давайте подведем итоги и выявим преимущество и недостатки цикла событий из преимуществ можно выделить возможность обрабатывать большое количество операций ввода-вывода если они простые то скорость достигается максимальная таких скоростей нельзя добиться используя потоки и блокирующую модель поведения это значительный плюс но также есть и минусы получается достаточно много асинхронного кода и также сложные вычисления создают большую нагрузку то есть обратиться к базе данных обработать сетевой запрос это все будет работать очень быстро а провести какие-то сложные математические операции в цикле это уже задача не из простых и она будет достаточно ресурсоемкой То есть как видите есть и плюсы и минусы У данного подхода начнем с классической модели если ее так можно назвать заблокирующего ввода вывода так работают классические веб-сервера например на Java концепция достаточно простая есть некоторые поток выполнения который строчка за строчкой выполняет какие-то команды какие-то инструкции пока команда у нас не выполнилась следующая перейти мы не можем то есть весь поток блокируется если инструкции простые все хорошо строчка за строчкой мы их выполняем никаких трудностей не возникает Но не все инструкции бывают простые иногда нам надо записать файл получить файл работать с базой данных или сетью как в данном примере При этом при блокирующей модели поведения весь поток у нас блокируется то есть поток занят какой-то трудоемкой операции ввода или выводы например он считывает файл с диска или же этот файл записывает при этом приложение не способно обрабатывать другие операции для того чтобы решить эту проблему подобные операции выполняют в разных потоках то есть на уровне операционной системы создаются потоки которые обрабатывают разные операции какие-то обрабатывают http соединение какие-то потоки взаимодействуют с базой данных какие-то потоки взаимодействуют с файловой системой такой подход является отличным решением но он имеет определенные минусы первые один из самых важных минусов что поток потребляет большое количество ресурсов при этом зачастую возникают ситуации когда поток создается но какую-то часть времени он просто простаивает но ресурсы для этого потока операционной системы уже были выделены и второй важный недостаток это сложность управление этими потоками то есть программист который пишет код и пытается с ними взаимодействовать должен обладать хорошей квалификацией потому что потоки могут обращаться к одним и тем же участкам памяти возникают так называемый дедлоки то есть взаимная блокировка рассмотрим некоторую схему есть некоторые веб-сервер который прослушивает некоторые запросы с веб-сервером устанавливается первое соединение И для него создается отдельный поток внутри потока выполняется какая-то операция по обработке данных и затем СПУ через какое-то время выполняется вторая операция параллельно с первым соединением устанавливается второе для него также создается поток С какой-то обработкой данных и также параллельно устанавливается третье соединение для него выделяется новый поток внимательно Изучите эту схему и вникните в то что здесь происходит понимание всех процессов улучшит дальнейшее обучение и так как видно на схеме потоки некоторое время находятся в состоянии простоя ожидая новых данных получаемых связанных с ним соединений при этом потоке потребляют значительное количество ресурсов они расходуют памяти вызывают переключение контекста поэтому иметь Достаточно долго выполняющийся поток для каждого подключения и при этом не использовать его длительную часть времени это не лучшее решение с точки зрения эффективности ярчайший пример для сравнения блокирующий и не блокирующие модели поведения это два веб-сервера Апач и энджинкс а патч на каждое входное соединение создавал отдельный поток и работал по блокирующей схеме candings чуть позже когда обсудим не блокирующую модель поведения теперь поговорим про неблокирующий Вот и вывод опять же есть некоторые веб-сервер работающий по этой модели и Извне установлено несколько сетевых подключений и сервер работает только с одним потоком с так называемым главным потоком или же maint Red при использовании не блокирующего ввода и вывода системные вызовы немедленно возвращают управление при этом не ожидая выполнения чтения или записи каких-либо данных подобный механизм доступа к ресурсам поддерживает большинство операционных систем и основным шаблоном реализации неблокирующего ввода и вывода является активный опрос ресурсов в цикле поскольку мало создать операцию и забыть про неё Нам необходимо получить еще и результат ее работы подобный шаблон подобный паттерн называется цикл ожидания это простейший паттерн простейший шаблон который Определенно не является идеальным способом который предназначен для неблокирующей работы с ресурсами но большинстве операционных систем есть более эффективный механизм для неблокирующей работы и он называется демультиплексор событий о нем мы поговорим чуть позже более детально как я уже сказал Apache работал по блокирующей модели поведения Где на каждое соединение открывался новый поток в свою очередь enginex сработал по неблокирующему принципу ввода и вывода при этом на графике Вы можете заметить что при росте одновременных подключений количество запросов которые мог обрабатывать Апач значительно ниже чем количество запросов которые обрабатывала Джинкс таким образом в примерно в два с половиной раза быстрее чем Апач Итак подведем итоги Джинкс использовал не блокирующую модель ввода/вывода а патч был классическим многопоточным веб-сервером Итак на данный момент мы разобрались с тем что представляет из себя неблокирующий вот вывод и поняли то что но Джейс работает Именно по этому принципу исходя из этой схемы может возникнуть вполне резонный вопрос получается что у нас есть один главный поток и получается что но Джейс однопоточный Это и так и не так одновременно Давайте попробуем разобраться сам по себе JavaScript является однопоточным и вся асинхронность достигается за счет так называемого эвентлуб цикла событий Что же касается НОД JS сам по себе not JS однопоточный то есть разработчики которые создают приложение на not.js пишут асинхронный код без использования потоков но при этом чуть ранее я упоминал что в основе но Джес лежит лебеви который занимается как раз операциями ввода и вывода своей основе лебеви может управлять потоками причем дефолт на их количество равняется четырем Это количество можно изменять Из минусов не блокирующего ввода и вывода можно выделить то что операции подобные чтению файла или записи его на диск являются очень тяжелыми поскольку выполняются в одном потоке хоть с использованием не блокирующего ввода и вывода поэтому некая распараллеливание этих процессов все же необходимо в свою очередь по умолчанию под капотом используют 4 потока Но для нас как для программистов на not.js это особой роли не играет просто воспримем это как факт Итак но Джейс однопоточный но при этом Levi используют потоки лебеви написан на C а движок V8 на котором основан на GS написан на c++ И как вы наверное уже могли догадаться и насильно си плюс плюс можно писать какие-то модули для node.js И это говорит нам о том что некоторые библиотеки могут использовать потоки и давайте рассмотрим вот такой пример Однажды я наткнулся на этот пример он мне показался очень хорошим для демонстрации и Давайте посмотрим Итак импортируем стандартный модуль но Джес Крипто который предназначен для криптографических операций для шифрования дешифрование и хеширование соответственно вызываем функцию которая шифрует какой-то пароль некоторые ключ за определенное количество итераций первым параметром укажем любой строковый пароль затем укажем соль которая необходима для хеширования затем укажем количество итерации сделаем их побольше чтобы этот процесс занимал какое-то время и мы наглядно могли увидеть затем указываем длину ключа и алгоритм шифрования на это пока что вообще не заостряйте внимание пример будет чуть в другом пока что необходимо просто запустить эту функцию которая будет хешировать последним аргументом мы передали callback он отработает именно в тот момент когда функция хеширования будет закончена эта функция как раз является асинхронной именно не блокирующий то есть поток при ее вызове заблокирован не будет и Давайте теперь проверим сколько эта функция по времени будет выполняться из текущей даты отнимем Дату когда скрипт у нас запустился то есть создадим переменную и туда поместим текущее время а затем из текущего времени Вот это стартовое время мы просто вычтем Итак запускаем Вот это время в формате timestemp в миллисекундах это стартовое время А сама функция хеширования отработала за 800 миллисекунд плюс-минус Теперь давайте копируем вызов этой функции и вызовем ее еще раз единицу влогах поменяем на двойку чтобы видеть разницу и запустим еще раз Как видите и первая и вторая функция результат вернули примерно в одно и то же время 950 плюс минус миллисекунд то есть они вызвались как-то параллельно Неважно как но параллельно теперь продублируем вызов функции еще несколько раз и запустим немного подождем и видим что четыре раза вызвалась функция и при этом время выполнения примерно секунда 200 опять же все логично все выполняется параллельно но попробуем добавить еще 5 вызов и посмотрим как отреагирует программа Как видите Первые 4 отработали плюс-минус в одно время но 5 запуск выбился и отработал гораздо позже Давайте запустим еще раз ситуация здесь примерно такая же первые четыре запуска закончили примерно в одно время а пятый закончил выполнение на 500 миллисекунд позже почему же так происходит рассмотрим на одну схему есть некоторые планировщик потоков планировщик это часть операционной системы которая отвечает за параллельно выполнение задач потоков процессов и вот как раз планировщик выделяет этим потоком некоторая процессорное время память стек и прочие ресурсы также есть некоторые пул потоков и в нем находится в данном случае 4 потока мы пять раз пытаемся запустить криптографическую функцию и Давайте посмотрим как потоки будут выполнять эти функции первый поток забирает запуск первая криптографической функции Второй второй третий и четвертый Четвертый по умолчанию 4 потока поэтому каждый из этих потоков взял на себя выполнение одной из криптографических функций 5 при этом осталась ожидать 4 функции выполнились примерно в одно время при этом все потоки освободились и тот из потоков который освободился раньше забирает на себя пятую функцию именно этим поведением объясняется то что пятая функция выполнена примерно на 500-600 миллисекунд позже чем предыдущие 4 теперь Вернемся опять к этой схеме как я сказал библиотеки могут быть многопоточными и мы в этом сейчас на примере убедились и так как мы уже обговорили для нас как для разработчиков но Джейс однопоточны из потоками напрямую мы не работаем но хочется сделать сразу некоторую помарку периодически в специфических ситуациях все же работа с потоками была необходима с версии 11.7 в not.js был введен модуль который называется worker trades и с помощью него можно управлять потоками и так мы убедились в том что не блокирующий ввод и вывод это быстро круто но как он работает пока что непонятно Давайте с этим разбираться современные операционные системы предоставляют некоторые механизм который называется демультиплексор событий именно благодаря демультиплексору событий неблокирующий ввод и вывод становится доступен рассмотрим Как работает де мультиплексор событий а также шаблон реактор на котором устроен но Джесс начнем с мультиплексора событий он представляет из себя некоторые интерфейсы уведомления о событиях его задача осуществляется в сборке и постановке в очередь событий ввода и вывода которые поступают из набора наблюдаемых ресурсов а также блокировка появления новых доступных для обработки событий следующая не менее важная запчасть всего механизма работы шаблона реактор это эвентлуп есть некоторая очередь событий и есть некоторые бесконечный цикл тот самый эвентлуп который синхронно выполняет зада исходя из этой очереди и распределяет их дальше очередь содержит в себе некоторые события например было отправлено какое-то сообщение например закончилось время у таймера и для каждого события устанавливается некий обработчик в not JS он представлен функцией обратного вызова так называемым колбэком Итак есть мультиплексор событий некоторые бесконечный цикл и очередь событий логично что должно быть какое-то приложение которое будет ожидать запрос ввода и вывода в нашем случае это приложение на not.js запросом ввода и вывода может быть опять же любой сетевой запрос запрос на чтение или запись файла обращение к базе данных и так далее и после того как операция ввода/вывода была закончена ее необходимо обработать этим также занимается приложение Итак На данном этапе У нас есть мультиплексор событий который представляет из себя некоторые интерфейс уведомления о событиях некоторые бесконечный цикл Event loop и ведь которая содержит в себе события и их обработчики также есть приложение которое ожидает запрос ввода и вывода и обрабатывает как раз эти события теперь рассмотрим последовательность взаимодействия этих компонентов шаблоне реактор Итак первый этап приложение создает новую операцию ввода и вывода передав запрос демультиплексору событий также приложение должно определить обработчик в нашем случае как я уже сказал Эта функция обратного вызова обработчик будет вызван тогда когда операция будет завершена самый важный момент что отправка нового запроса для демультиплексора событий не приводит к блокировке приложения управление немедленно возвращается обратно к приложению во втором этапе происходит следующее после завершения обработки набора операций ввода и вывода демультиплексор событий добавляет эти новые события в очередь на третьем этапе цикл событий выполняет обход элементов в очереди событий после чего для каждого это событие вызывается соответствующей обработчик то есть функция обратного вызова которая была указана для того или иного события на пятом этапе отметим две ситуации в случае 5А обработчик который является частью кода приложения возвращает управление циклу событий то есть какое-то событие мы обработали и опять вернули управление циклу событий Event loop но во время выполнения этого обработчика вполне могут запрашиваться какие-то новые асинхронные операции например мы прочитали какую-то информацию из базы данных и теперь хотим записать ее файл это приводит к добавлению новых операций в мультиплексор событий и вся вот эта вот схема повторяется по новой после того как эвент-клуб обработал все элементы из очереди цикл вновь заблокируется этим мультиплексором событий и вся эта процедура начнется по новой Когда появится новый запрос на операцию ввода и вывода каждая операционная система имеет свой интерфейс для демультиплексора событий название этих интерфейсов Вы можете видеть на этом слайде поскольку в каждой операционной системе интерфейсы разные и например в unix обычные файлы не поддерживают не блокирующих операций поэтому для имитации не блокирующей модели поведения необходимо использовать отдельный поток вне цикла событий то есть нужна некоторая абстракция которая для всех операционных систем будет делать не блокирующую модель поведения одинаковой и предсказуемой именно по этой причине разработчики ядра платформы но GS разработали библиотеку на си на которой мы говорили за счет нее как раз обеспечивается совместимость но Джес со всеми основными платформами библиотека libuy реализует шаблон реактор о котором мы говорили несколько минут назад и обеспечивает программный интерфейс для создания циклов событий управления очереди событий выполнение электронных операций ввода-вывода и организации очереди задач разных типов теперь поговорим про эвентлуб в nod.js и информация которая сейчас будет представлена эта информация из официальной документации not.js Итак когда not JS запускается она инициализирует некоторый цикл событий то есть эвентлуп но Джейс обрабатывает предоставленный на вход код который может выполнять вызов асинхронного API настраивать какие-то различные таймеры и так далее после чего начинается обработка цикла событий диаграмма которую вы видите на слайде показывает порядок выполнения операций цикле событий каждый из представленных сегментов на слайде представляет из себя некоторую фазу цикла событий каждая из этих фаз имеет очередь калбеков для выполнения когда цикл событий входит фазу он будет выполнять любые операции относящиеся к этой фазе Затем он будет выполнять калбэки из очереди пока это очередь не будет исчерпана после того как он выполнит все колбеки он переходит на следующую фазу и проделывает подобную процедуру теперь кратко разберем фазы первая фаза это таймеры в этой фазе выполняются колбеки которые запланированы двумя функциями сет тайм-аут и сет-интервал наверняка многие из вас этими функциями уже знакомы вторая фаза это калбеки ввода и вывода здесь выполняются почти все колбеки за исключением событий Close таймеров и событий которые были определены с помощью функции Set mediate в not.js следующая фаза ожиданий подготовка и она используется только для внутренних целей следующая фаза опрос в ней происходит получение новых событий года и вывода при этом not JS может блокироваться на этом этапе на этапе Проверка вызываются как раз те самые калбеки которые были определены с помощью функции Set и mediate и заключительным этапом вызываются все калбеки события Close например закрытие вебсокет соединение то есть события Close закрытие например стрима считывающего какие-то данные и вот так проходит все фазы выполняет колбеки из очереди и запускается по новой То есть если на текущем этапе сравнить но GS Event Loops и браузерным то уже можно заметить что в браузерном у нас было всего две очереди это очередь микро и макро задач то здесь у нас появляется 6 очередей которые последовательно выполняются таймер и колбэки ожидания опрос проверка калбеки closs то есть они вот в таком вот формате одна за одной выполняются задачи из этих очередей выполняются если быть точным здесь нет никаких микро тасок макро тасок сам эвентлуп этого не подразумевает здесь просто есть очереди которые внутри себя содержат колбеки определенного вида Но на самом деле если быть более справедливым очередей по факту будет 7 потому что почему-то вот в документации когда вот Event loop рисуют здесь не подразумевают промисы про Мисси в любом случае будут выполняться перед таймерами и в этом Вы можете убедиться написав простой примерчик и запустив его промисы в любом случае всегда будут иметь больше приоритет чем какие-то другие колбеки таймеры и так далее ну и Подводя итог можно сделать вывод о том что Event loop что в браузере что в not.js что в любой другой технологии Он решает по сути одну задачу задачу асинхронности при этом какие-то детали реализации очереди то как события в эти очереди попадают то как они оттуда выходят это Все индивидуально в каждом реализованном механизме эвен-клупа это все детали а глобально Он решает задачу асинхронности при этом увидели что в браузере но Джеймс клуб действительно отличается и работает немного по-разному еще напоследок Хочется Вам показать несколько интересных примерчиков в коде с промисами с таймаутами вообще с тем как выполняются задачи и какие петли циклы могут образовываться совсем недавно собеседование меня спросили про кейс который случился у людей в продакшене у них работала нода и в каком-то из кейсов случалось Так что промиз зацикливался сам на себя это происходило не явно где-то там обрабатывался запрос было какой 4 чтение например из базы данных и получалось так что вот промез зацикливался и из-за этого естественно приложение крашилось долго не могли понять почему потому что ну это не всегда бывает очевидно Кстати это собеседование в Корпорацию всеми известную я проходил его не так давно и ролик у меня записаны есть я его пока на канал не выкладываю если интересно посмотреть опять же дайте мне знать об этом в комментарии при берем этот ролик на лучшие времена и обязательно в какой-то ближайшее время я его выложу если будет интерес но мы давайте рассмотрим пример есть вот такая вот функция реку сильно аргументом она принимает про Мисс возвращает она вот такую вот конструкцию кроме Zen внутри мы влоги выводим просто про Мисс 1 и опять вызываем рекурсивно эту функцию и внутрь Передаем промез resolve Но первый раз мы эту функцию вызываем вот здесь ниже ну и соответственно так вот оно в цикле все будет крутиться кроме срезов для тех кто не знает возвращает как раз промиз и чуть ниже смотрите у нас есть вот такой сайт тайм-аут который по идее никогда в жизни У нас не вызовется за счет того что очередь микро тасок в нашем случае это Event loop там другие очереди Она всегда будет переполняться и Обратите внимание что вот так вот рекурсивно зациклившись на промез У нас вот этот бесконечный поток который черпает из одной очереди эти промисы крутятся бесконечно при этом сет тайм-аут у нас вообще никогда вызван не будет похоже ситуация вот здесь Здесь у нас бесконечный цикл обычный for И в нем мы внутри выводим логин и вот здесь у нас есть промез resolve в котором мы просто влоги тоже выводим текущие элементы итерации и в таком случае у нас промис также выполнен никогда у нас бесконечно будет инкрементироваться цикл это синхронные задачи они попадают в колл-стек и при этом промисс вот это вот очередь промисов никогда выполнена не будет тоже решил эти пару примеров добавить вам для демонстрации Как по мне тоже интересно раскрывает Вот эту вот тему асинхронности и вот всякие вот циклы петли которые могут образовываться и которые не позволят выполнить задачи из соседних очередей которые должны идти в очереди как бы следующими по выполнению и на этом все друзья постарался сделать супер подробный наглядный визуально приятный ролик про эвент-клуб браузер но GS и на текущий момент мне кажется даже в англоязычном сегменте более подробный ролик ну просто не найти по крайней мере при подготовке своего материала я что-то более подробное найти не смог объединил куча источников куча статей все что можно было найти нашел и постарался в этот ролик добавить надеюсь вам было полезно интересно ну я в свою очередь попрошу от вас малого поставить лайк и комментарий для лучшего продвижения этого ролика но я пошел делать следующее видео Всем спасибо всем пока
The words are the caption track's own and nothing is reworded or re-transcribed. Paragraph breaks are placed between sentences so the text reads as prose.
Free tools for your own script. No signup, no login.
Paste your draft and see where viewers are likely to drop off, with a rewrite for each weak line.
Paste the first 30 seconds of your own draft for a hook score and rewrites.
Check your draft against YouTube's advertiser-friendly guidelines before you record it.
Read this channel's public videos and transcripts, and download a writing brief for it.
Most replayed moment #1
17:083.0x the video's typical replay level
используется V8 в No JS у нас используется V8 Однако устройство цикла событий в них разное и когда мы будем разбирать not JS в конце этого ролика вы в этом Убедитесь Итого вернемся к вопросу если у нас движок JavaScript предоставляет Call стек а очередь задач
Said at 17:00
Most replayed moment #2
1:02:342.5x the video's typical replay level
называется демультиплексор событий именно благодаря демультиплексору событий неблокирующий ввод и вывод становится доступен рассмотрим Как работает де мультиплексор событий а также шаблон реактор на котором устроен но Джесс начнем с мультиплексора событий
Said at 1:02:28
Most replayed moment #3
2:142.4x the video's typical replay level
URL нажимаем на кнопки вперед назад где различные настройки и все С чем мы в принципе взаимодействуем через UI далее еще одна составная часть браузера Это непосредственно сам браузерный движок это такая соединительная часть между пользовательским интерфейсом и
Said at 2:07
The graph counts replays. It does not show where viewers stopped watching.
Sentence shape
| Measure | This transcript |
|---|---|
| Sentences | 1 |
| Average words per sentence | 10636.0 |
| Longest sentence | 10,636 words |
| Questions asked | 0 |
| Sentences containing a number | 1 |
Most used terms