Как работает Event Loop в JavaScript?

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


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

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

Эта статья посвящена одному из очень важных, но редко понимаемых понятий или терминов в JavaScript. ЦИКЛ СОБЫТИЙ!. 

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

Прежде чем мы сможем понять, как работает цикл обработки событий, мы должны сначала понять, что такое сам JavaScript и как он работает.!

Что такое JavaScript?

Прежде чем мы продолжим, я хотел бы, чтобы мы сделали шаг назад к самым основам. Что на самом деле такое JavaScript? Мы могли бы определить JavaScript как;

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

Подожди, что это? Книжное определение? ��

Давайте разберемся с этим!

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

Единственная нить

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

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

Как JavaScript может быть однопоточным и неблокирующая в то же время?

Но что означает блокировка?

Неблокируемая

Нет единого определения блокировки; это просто означает вещи, которые медленно работают в потоке. Таким образом, неблокирование означает вещи, которые не замедляются в потоке.

Но подождите, я сказал, что JavaScript работает в одном потоке? И я также сказал, что это неблокирование, что означает, что задача быстро выполняется в стеке вызовов? Но как??? Как насчет того, когда мы запускаем таймеры? Loops?

Расслабьтесь! Мы узнаем немного.

параллельный

Параллельность означает, что код выполняется одновременно более чем одним потоком..

Ладно, дела идут действительно странный Теперь, как JavaScript может быть однопоточным и одновременно работать одновременно? то есть выполнение его кода с более чем одним потоком?

Асинхронный

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

Но у JavaScript есть одна нить? Что тогда выполняет этот код блокировки, позволяя другим кодам в потоке выполняться?

Прежде чем мы продолжим, давайте подведем итоги.

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

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

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

Двигатель V8

Движок V8 – это высокопроизводительный движок исполнения веб-сборки с открытым исходным кодом для JavaScript, написанный на C ++ компанией Google. Большинство браузеров запускают JavaScript с использованием движка V8, и даже популярная среда выполнения узлов js тоже использует его.

Говоря простым языком, V8 – это программа на C ++, которая получает код JavaScript, компилирует и выполняет его..

V8 делает две основные вещи;

  • Распределение памяти кучи
  • Контекст выполнения стека вызовов

К сожалению, наше подозрение было неверным. V8 имеет только один стек вызовов, думайте о стеке вызовов как о потоке.

Один поток === один стек вызовов === одно выполнение за раз.

Изображение – Хакер полдень

Поскольку V8 имеет только один стек вызовов, как тогда JavaScript работает одновременно и асинхронно, не блокируя основной поток выполнения?

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

JavaScript выполняет каждый код построчно, один за другим (однопоточный). Как и ожидалось, первая строка печатается здесь в консоли, но почему последняя строка печатается перед кодом тайм-аута? Почему процесс выполнения не ожидает код тайм-аута (блокирование) перед тем, как выполнить последнюю строку?

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

Давайте взглянем на V8 Исходный код какое-то время.

Чего ждать??!!! В V8 нет функций таймера, нет DOM? Нет событий? Нет AJAX?…. Yeeeeessss!!!

События, DOM, таймеры и т. Д. Не являются частью основной реализации JavaScript, JavaScript строго соответствует спецификациям Ecma Scripts, и различные его версии часто упоминаются в соответствии с его спецификациями Ecma Scripts (ES X).

Рабочий процесс выполнения

События, таймеры, Ajax-запросы все предоставляются на стороне клиента браузерами и часто называются Web API. Именно они позволяют однопоточному JavaScript быть неблокирующим, параллельным и асинхронным! Но как?

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

Стек вызовов

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

Давайте рассмотрим приведенный ниже пример;

Источник – https://youtu.be/8aGhZQkoFbQ

Когда вы вызываете функцию printSquare (), она помещается в стек вызовов, функция printSquare () вызывает функцию square (). Функция square () помещается в стек и также вызывает функцию multiply (). Функция умножения помещается в стек. Так как функция умножения возвращает и является последней вещью, которая была помещена в стек, сначала выполняется ее получение, и она удаляется из стека, затем следует функция square (), а затем функция printSquare ()..

Веб-API

Именно здесь код, который не обрабатывается механизмом V8, выполняется, чтобы не «блокировать» основной поток выполнения. Когда стек вызовов сталкивается с функцией веб-API, процесс немедленно передается веб-API, где он выполняется, и освобождает стек вызовов для выполнения других операций во время его выполнения..

Давайте вернемся к нашему примеру setTimeout выше;

Когда мы запускаем код, первая строка console.log переносится в стек, и мы получаем наш вывод почти сразу, по достижении тайм-аута таймеры обрабатываются браузером и не являются частью базовой реализации V8, а выталкиваются вместо веб-API, освобождая стек, чтобы он мог выполнять другие операции.

Пока тайм-аут все еще работает, стек переходит к следующей строке действий и запускает последний файл console.log, который объясняет, почему мы получаем его до вывода таймера. Как только таймер завершен, что-то происходит. В этом случае console.log в таймере снова волшебным образом появляется в стеке вызовов!

Как?

Цикл событий

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

Возвращаясь к нашему примеру тайм-аута, когда веб-API завершает выполнение задачи, он не просто автоматически возвращает его обратно в стек вызовов. Это идет к Очередь задач. 

Очередь – это структура данных, которая работает по принципу «первым пришел – первым вышел», поэтому, когда задачи помещаются в очередь, они выходят в том же порядке. Задачи, выполненные веб-API, которые помещаются в очередь задач, затем возвращаются в стек вызовов, чтобы распечатать их результаты..

Но ждать. ЧТО ТАКОЕ ПРОВЕРКА???

Источник – https://youtu.be/8aGhZQkoFbQ

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

Источник – https://www.quora.com/How-does-an-event-loop-work/answer/Timothy-Maxwell

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

Вывод

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

JavaScript всегда по требованию, и если вам интересно узнать, я бы посоветовал вам проверить это Курс удэми.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map