Event loop js что это
Перейти к содержимому

Event loop js что это

  • автор:

Как работает event loop в javascript

С помощью механизма Event Loop (Цикл событий) становится возможным выполнять асинхронный код в JavaScript.

Event Loop — это специальный механизм на уровне движка js, который координирует работу трёх сущностей: Call Stack (стэк вызовов), Web API (API, предоставляемый браузером), Callback Queue (очередь колбэков).

Работают они следующим образом: движок js анализирует код. Когда он встречает вызов какой-то функции, он перемещает эту функцию в Call Stack. Если эта функция синхронная (например, console.log() ), то она сразу же исполняется, покидает стэк и на её место приходит следующая функция. Если же эта функция асинхронная, например, setTimeout() , обработчик событий, сетевой запрос и т.д., то на помощь приходит браузер со своим Web API (мы же помним, что JavaScript — это однопоточный язык, и сам работать в многопоточном режиме он не может). Event Loop перемещает колбэк асинхронной функции в Web API, а сама асинхронная функция уходит из стэка вызовов. То есть, пока колбэк асинхронной функции находится под управлением Web API, движок js продолжает выполнять другие операции!

Что же происходит с колбэком? В случае, например, setTimeout() , Web API ожидает истечения указанного времени, затем Event Loop перемещает этот колбэк в Callback Queue (очередь колбэков). Когда стэк вызовов освобождается, Event Loop перемещает в него наш колбэк из очереди колбэков, после чего колбэк наконец исполняется и покидает стэк вызовов.

Этот процесс повторяется до тех пор, пока весь js код не будет выполнен.

Здесь представлен наглядный пример работы Event Loop, очень советую ознакомиться!

01 октября 2022

Код JavaScript работает только в однопоточном режиме. Это означает, что в один и тот же момент может происходить только одно событие. С одной стороны это хорошо, так как такое ограничение значительно упрощает процесс программирования, здесь не возникает проблем параллелизма. Но, как правило, в большинстве браузеров в каждой из вкладок существует свой цикл событий. Среда управляет несколькими параллельными циклами. Общим знаменателем для всех сред является встроенный механизм, называемый Event Loop (Цикл событий) JavaScript, который обрабатывает выполнение нескольких фрагментов программы, вызывая каждый раз движок JS. Цикл событий — ключ к асинхронному программированию на JavaScript. Подробнее.

14 января 2023

Хотел бы еще добавить. В ES6 вместе с промисами появилось понятие очередь микротасков. Эта очередь используется промисами и обладает более высоким приоритетом, по сравнению с очередью макротасков (Например setTimeout или SetInterval). Это означает, что промисы будут выполняться раньше, чем вызовы из обычной очереди колбеков.

 , 0); setTimeout(() => , 0); new Promise((resolve, reject) => ) .then(res => console.log(res)); new Promise((resolve, reject) => ) .then(res => console.log(res)); //Вывод Promise 1 resolved Promise 2 resolved setTimeout 1 setTimeout 2 

Event loop¶

Event loop (или цикл событий) позволяет выполнять однопоточному Node.js неблокирующие операции ввода/вывода, передавая их выполнение ядру системы, когда это возможно.

Стадии event loop¶

Кратко работу event loop Node.js можно описать так: операция передается на выполнения ядру системы, после завершения Node.js получает уведомление в том, что определенная для операции callback-функция может быть добавлена в очередь выполнения.

Инициализация event loop происходит в момент запуска сервера Node.js, и с этого момента он начинает свою работу, которую можно разделить на несколько этапов:

timers : выполнение callback-функций, зарегистрированных функциями setTimeout() и setInterval() ;

pending callbacks : вызов callback-функций операций ввода/вывода, выполнение которых было отложено на предыдущей стадии цикла событий;

idle, prepare : выполнение внутренних действий, необходимых самому event loop;

poll : выполнение callback-функций завершенных асинхронных операций и управление фазой timers;

check : выполнение callback-функций, зарегистрированных функцией setImmediate() ;

close callbacks : обработка внезапно завершающихся действий.

На стадии timers выполняются зарегистрированные таймерами функции, причем переход на стадию контролируется стадией poll. Из-за блокировки стадией poll цикла событий, таймеры могут выполняться с некоторой задержкой, т. е. через больший интервал времени, чем тот, который был задан. Рассмотрим ситуацию на примере.

1 2 3 4 5 6 7 8
let request = require('request'); setTimeout(() => console.log('Timeout'), 25); //предполагаем, что запрос выполняется 20 миллисекунд, а callback - 10 миллисекунд request('http://www.example.com', (error, response, body) => console.log('Response: ', response) ); 

В примере сперва вызывается функция setTimeout() , которая должна выполнить переданную ей функцию через 25 миллисекунд. Затем сразу же делает запрос к удаленному API, занимающий 20 миллисекунд. В момент завершения запроса до вызова функции в таймере останется еще 5 миллисекунд, поэтому event loop начнет выполнять callback-функцию, определенную для обработки результата запроса, выполнение которой занимает 10 миллисекунд. Получается, что в предполагаемый момент времени выполнение таймера будет невозможным из-за занятости цикла событий и его вызов произойдет по окончанию работы callback-а запроса, а именно через 30 миллисекунд после определения самого таймера.

Результат работы кода.

Response: Timeout 

При pending callbacks выполняются действия, отложенные на предыдущей итерации event loop. Например, это могут быть сообщения об ошибках, которые не были выведены ранее из-за попытки системы их исправить.

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

Если очередь оказывается пустой, то проверяется наличие действий, заданных функцией setImmediate() , и если таковые имеются — происходит переход на стадию check, в противном случае Node.js event loop проверит, есть ли таймеры для выполнения. Если таймеры имеются — произойдет переход на timers, если нет — event loop будет ждать добавления в очередь новых callback-ов и при их появлении сразу же начинать их выполнение.

Для недопущения длительной блокировки event loop, в Node.js имеется ограничение на количество выполняемых на стадии poll callback-функций.

На стадии close callbacks вызываются функции, зарегистрированные для действий, возникающих внезапно. например, событие close или disconnect для сокет соединения.

process.nextTick()¶

Node.js process.nextTick() позволяет выполнять переданные ему callback-функции в текущий момент времени, вне зависимости от того, на какой стадии находится выполнение event loop. Выполнение самого event loop продолжится сразу после завершения всех переданных process.nextTick() callback-ов.

process.nextTick(() => console.log('After')); console.log('Before'); 

Выполнение переданной process.nextTick() callback-функции начинается сразу после завершения текущей итерации event loop.

Асинхронность Event loop

@serverSerrverlesskiy

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

Любые данные от сервера запрашиваются асинхронно: отправляется запрос (XMLHttpRequest или XHR), и код не ждёт его возвращения, продолжая выполняться. Когда же сервер отвечает, объект XHR получает уведомление об этом и запускает функцию⚙️ обратного вызова — callback , который передали в него перед отправкой запроса.

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

Видео​

Event loop​

Event loop в JavaScript — менеджер асинхронных вызовов.

Чтобы этот хитрый процесс слаженно работал, в JavaScript реализован механизм для управления очерёдностью исполнения кода . Поскольку это однопоточный язык , возникла необходимость «вклиниваться» в текущий контекст исполнения. Этот механизм называется event loop — событийный цикл.

С английского loop переводится как «петля», что отлично отражает смысл: мы имеем дело с закольцованной очередью.

Event loop регулирует последовательность исполнения контекстов — стек. Он формируется, когда сработало событие или была вызвана функция⚙️. Реакция на событие помещается в очередь исполнения, в event loop , который последовательно, с каждым циклом выполняет попадающий в него код . При этом привязанная к событию функция⚙️ вызывается следующей после текущего контекста исполнения.

В JavaScript постоянно работают связанные между собой синхронная и асинхронная очереди выполнения. Синхронная — stack — формирует очередь и пробрасывает в асинхронную — event loop — вызовы функций⚙️, которые будут выполнены после текущего запланированного исполняемого контекста.

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

Описание​

JavaScript это однопоточный язык: одновременно может выполняться только одна задача. Обычно в этом нет ничего сложного, но теперь представьте, что вы запускаете задачу, которая занимает 30 секунд. Да. Во время этой задачи мы ждем 30 секунд, прежде чем что-либо еще может произойти (по умолчанию JavaScript запускается в главном потоке браузера, поэтому весь пользовательский интерфейс будет ждать) Сейчас 2021 год, никто не хочет медленный сайт который тупит.

К счастью, браузер предоставляет нам некоторые функции, которые сам механизм JavaScript не предоставляет: Web API. Который включает в себя DOM API, setTimeout, HTTP-запросы и так далее. Это может помочь нам создать асинхронное неблокирующее поведение .

Когда мы вызываем функцию, она добавляется в call stack(стек вызовов). Стек вызовов является частью механизма JS, это не зависит от браузера. Это классический взгляд на стек, т.е first in , last out . Когда функция возвращает значение, она «выталкивается» из стека.

function great()   return 'Hello' >  function respond()   return setTimeout(() => alert('Hey!'), 1000) >  great() respond() 

Функция respond возвращает функцию setTimeout . SetTimeout предоставляется нам через Web-API : он позволяет нам делить задачи, не блокируя основной поток. Callback функция, которую мы передали в функцию setTimeout , лямбда функция () => добавляется в Web-API . Тем временем setTimeout и responde извлекаются из стека и возвращают свои значения.

В Web-API таймер работает до тех пор, пока второй аргумент, который мы передали ему, не подождет 1000 мс. Callback не сразу добавляется в стек вызовов, а передается в нечто, называемое очередью.

Это может сбивать с толку: это не означает, что callback функция добавляется в стек вызовов (таким образом, возвращает значение) через 1000 мс! Он просто добавляется в очередь через 1000 мс. Но в этой очереди, функция должна ждать пока придет ее черёд.

Теперь это та часть, которую мы все ждали. Время для event loop выполнить единственную задачу: соединить очередь со стеком вызовов! Если стек вызовов пуст, то есть, если все ранее вызванные функции вернули свои значения и были извлечены из стека, первый элемент в очереди добавляется в стек вызовов. В этом случае никакие другие функции не были вызваны, что означает, что стек вызовов был пуст к тому времени, когда callback функция была первым элементом в очереди.

callback добавляется в стек вызовов, вызывается и возвращает значение, а также извлекается из стека.

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

const foo = () => console.log('First') const bar = () => setTimeout(() => console.log('Second'), 500) const baz = () => console.log('Third')  bar() foo() baz() 

Давайте посмотрим, что происходит, когда мы запускаем этот код в браузере:

Мы вызываем bar , которая возвращает функцию setTimeout . Callback который мы передали в setTimeout добавляется в Web API , функция setTimeout и bar извлекаются из стека вызовов.

Таймер запускается, тем временем foo вызывается и записывает в журнал First . foo возвращает undefined , baz вызывается и callback добавляется в очередь baz логирует Third . Цикл обработки событий видит, что коллстек пуст после возврата baz , после чего колбэк добавляется в стек вызовов. Callback логирует Second .

Надеюсь, что это заставит вас чувствовать себя более уверено с циклом событий event loop !

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

EnglishMoji!

Проблемы?​

Пишите в Discord или телеграмм чат, а также подписывайтесь на наши новости

Вопросы:​

  1. Инструмент, который выводит контекст исполнения функции из синхронного потока
  2. Инструмент, который исполняет код построчно
  3. Инструмент, который обрабатывает запросы параллельно с загрузкой веб-страниц

Менеджер асинхронных вызовов:

  1. stack
  2. Event loop
  3. Объекты высшего класса

Инструмент, выполняющий код с задержкой в миллисекундах:

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

EnglishMoji!

Ссылки:​

  1. Объяснение работы EventLoop в JavaScript
  2. Как управлять event loop в JavaScript
  3. Справочник javascript
  4. Статья: Объяснение Event Loop в Javascript с помощью визуализации
  5. Статья: JavaScript Visualized: Promises & Async/Await

Contributors ✨​

Thanks goes to these wonderful people (emoji key):

event loop js что это

С помощью механизма Event Loop (Цикл событий) становится возможным выполнять асинхронный код в JavaScript.

Event Loop — это специальный механизм на уровне движка js, который координирует работу трёх сущностей: Call Stack (стэк вызовов), Web API (API, предоставляемый браузером), Callback Queue (очередь колбэков).

Работают они следующим образом: движок js анализирует код. Когда он встречает вызов какой-то функции, он перемещает эту функцию в Call Stack. Если эта функция синхронная (например, console.log() ), то она сразу же исполняется, покидает стэк и на её место приходит следующая функция. Если же эта функция асинхронная, например, setTimeout() , обработчик событий, сетевой запрос и т.д., то на помощь приходит браузер со своим Web API (мы же помним, что JavaScript — это однопоточный язык, и сам работать в многопоточном режиме он не может). Event Loop перемещает колбэк асинхронной функции в Web API, а сама асинхронная функция уходит из стэка вызовов. То есть, пока колбэк асинхронной функции находится под управлением Web API, движок js продолжает выполнять другие операции!

Что же происходит с колбэком? В случае, например, setTimeout() , Web API ожидает истечения указанного времени, затем Event Loop перемещает этот колбэк в Callback Queue (очередь колбэков). Когда стэк вызовов освобождается, Event Loop перемещает в него наш колбэк из очереди колбэков, после чего колбэк наконец исполняется и покидает стэк вызовов.

Этот процесс повторяется до тех пор, пока весь js код не будет выполнен.

Здесь представлен наглядный пример работы Event Loop, очень советую ознакомиться!

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

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