Каждый JS-разработчик, или тот, кто хочет им стать, сталкивался или на собеседованиях, или на разборах собесов про задачки на событийный цикл. Сначала интервьюер спрашивает кратко про event loop, затем показывает кусок кода, где обычно есть несколько console.log(), и нас просят сказать очередность появления логов. Далее, дается ответ, и если он правильный, идут дальше, а если нет, интервьюер скажет свою последовательность (возможно даст небольшой комментарий) и также двинутся дальше. Очень редко, если вы ошиблись, вам подробно объяснят, что как и почему. Все-таки - собеседование.
Несколько месяцев назад моя супруга захотела перейти в другую компанию, и начала проходить собесы. И вот на после одного из них, я понял, что не всегда могу грамотно объяснить почему именно сейчас какая таска сработает, и поэтому решил углубиться в понимании и сейчас вам представлю мои размышления. Прошу воспринимать этот материал как открытый тред для рассуждения с некими вводными.
Event loop
Лучше, чем на https://learn.javascript.ru/event-loop теорию я не объясню, так что давайте сразу перейдем к задачкам.
Сначала разберем две задачки из статьи выше, а затем я покажу мои размышления по другим задачкам с реальных собесов.
Принцип решения задач на Event loop
Основное принцип в решении задачек на событийный цикл.
Выполняется основной поток кода (+ выполняются скрипты в теле создания промисов)
Выполняются микротаски
По факту, микротаски = промисы.
Также есть возможность принудительно микромизировать задачу с помощьюqueueMicrotask(f)
, но я так никогда не делал в рабочем коде. Если у кого есть опыт - пожалуйста, поделитесь.
(важно помнить, что исполняются ВСЕ промисы, и нужно об этом помнить, так как по факту, так можно застопорить процесс выполнения скриптов и очень не скоро приступить к макротаскам)Выполняется макротаска
Макротаска - это у нас или браузерное API, или манипуляции с DOM деревом (дополните меня в комментариях, пожалуйста)
Далее, цикл повторяется.
Если основной поток все и микрозадач тоже нет, последовательно выполняются макротаски.
Как я предлагаю решать задачи на event loop
В ходе решения задачек, я пришел к выводу, что можно использовать вот такую табличку, и с ее помощью неплохо упрощать себе жизнь.
Не стесняйтесь на собеседованиях использовать ее, лучше даже от руки, на бумажке.
Решение в голове, в стрессовой ситуации - большой шанс совершить ошибку.
Основной поток |
Микрозадачи |
Макрозадачи |
Заполняйте табличку так, чтобы каждый скрипт, был на отдельной строке! это важно.
Ну, давайте приступим. У нас есть простенькая задачка, уровня Junior.
ЗАДАЧА 1
setTimeout(function timeout() {
console.log('Таймаут');
}, 0);
let p = new Promise(function(resolve, reject) {
console.log('Создание промиса');
resolve();
});
p.then(function(){
console.log('Обработка промиса');
});
console.log('Конец скрипта');
Идем сверху-вниз, именно так, как это делает парсер нашего кода.
setTimeout(function timeout() { console.log('Таймаут'); }, 0);
Сначала, видим setTimeout
, это макрозадача (браузерное API), и мы должны его зарегистрировать (если не понятно что такое регистрация, предлагаю посмотреть это видео).
Помимо занесения результата выполнения скрипта в нашу табличку, укажем и время, через которое он должен сработать (время не точно, но гарантирующее задержку, то есть он сработает, не раньше, чем через N секунд).
Основной поток |
Микрозадачи |
Макрозадачи |
|
let p = new Promise(function(resolve, reject)
Заметим, что здесь у нас создается промис,
{ console.log('Создание промиса');
resolve(); });console.log('Создание промиса')
выполнится, т.к. это по сути основной поток, нам не важно, как завершится промис.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
p.then(function(){ console.log('Обработка промиса'); });
А тут, мы видим, что наш промис уже исполняется, видим цепочку. Следовательно, это микрозадача.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
И финальное, console.log('Конец скрипта');
Это основной поток.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
А дальше, остается самое простое и веселое. Собрать наш ответ, как бургер, по методичке.
Идем по нашему гайду:
Основной поток (все задачи)
Микрозадачи (все задачи)
Макрозадача
Repeat, please.
Итак, у нас получается
'Создание промиса'
'Конец скрипта'
'Обработка промиса'
'Таймаут'
ЗАДАЧА 2
Окей, давайте сразу решим вторую задачку, посложнее.
console.log(1);
setTimeout(() => console.log(2));
Promise.resolve().then(() => console.log(3));
Promise.resolve().then(() => setTimeout(() => console.log(4)));
Promise.resolve().then(() => console.log(5));
setTimeout(() => console.log(6));
console.log(7);
console.log(1)
- основной поток выполнения кода
Основной поток |
Микрозадачи |
Макрозадачи |
|
setTimeout(() => console.log(2))
- регистрируем макрозадачу в браузерное API, с нулевым сроком срабатывания
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
Promise.resolve().then(() => console.log(3))
- микрозадача
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
Promise.resolve().then(() => setTimeout(() => console.log(4)))
Тут интереснее, промис порождает макрозадачу. Для таких особых задачек, я добавляю стрелочку направо, мол, при исполнении промиса, перейдет в статус макрозадач. Не забываем, что есть нулевая отсрочка срабатывания
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
Promise.resolve().then(() => console.log(5))
- микротаска
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
setTimeout(() => console.log(6))
- макрозадача с нулевой отсрочкой срабатывания.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
||
|
И финальная, console.log(7)
- основной поток.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
||
|
||
|
Фух, заполнили. Давайте собирать наш ответ. Опять покажу наш гайд:
Основной поток (все задачи)
Микрозадачи (все задачи)
Макрозадача
Repeat, please.
Итак, у нас получается
console.log(1)
console.log(7)
console.log(3)
console.log(5)
console.log(2)
console.log(6)
console.log(4)
Тут нужно учесть, что console.log(4),0
встанет в конец очереди макрозадач. А там у нас уже находятся 2, 6, поэтому 4 идет в конец.
ЗАДАЧА 3
Окей, а теперь давайте решим похожую задачку с собеседования в один очень интересный, прогрессивный российский банк. У кого есть догадки, пишите в комменты.
Она очень похожа, но есть один нюанс.
console.log(1);
setTimeout(() => console.log(2));
Promise.reject(3).catch(console.log);
new Promise(resolve => setTimeout(resolve)).then(() => console.log(4));
Promise.resolve(5).then(console.log);
console.log(6);
setTimeout(() => console.log(7),0);
Прошу обратить внимание, на некоторую разницу в том, как записаны промисы, и будьте уверены, они так тоже прекрасно срабатывают и значения передадутся в функции console.log
Самый интересный кусочек здесь, это
new Promise(resolve => setTimeout(resolve)).then(()=>console.log(4))
Важно помнить!
Функция, переданная в конструкцию
new Promise
, называется исполнитель (executor). КогдаPromise
создаётся, она запускается автоматически.
Я уже пропущу подробное заполнение таблицы, надеюсь оно понятно.
console.log(1);
setTimeout(() => console.log(2));
Promise.reject(3).catch(console.log);
new Promise(resolve => setTimeout(resolve)).then(()=>console.log(4))
Вот тут хитрее. В момент выполнения executor'а регистрируется макротаска, при выполнении которой регистрируется микротаска.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
Ну и добьем нашу табличку, и будем собирать ответ.
solve(5).then(console.log);
console.log(6);
setTimeout(() => console.log(7),0);
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
||
|
||
|
Ну что, надеюсь пока все понятно. Начинаем аккуратно собирать ответ.
Опять же наш гайд. Надеюсь вы его уже выучили.
Основной поток (все задачи)
Микрозадачи (все задачи)
Макрозадача
Repeat, please.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
|
|
|
||
|
Итак, у нас получается 1 6 3 5 2 ...
Тут все ясно понятно. А вот что с четверкой? Макрозадача, порождает микрозадачу.
Когда очередь подходит к нашей хитрой четверке, то вспоминаем, что макрозадачи срабатывают не все, а лишь по одной, а потом цикл проверяется очередь основного потока и микрозадач. А у нас получается, что макрозадача порождает микрозадачу, выполняет ее, и лишь потом берет следующую макрозадачу. Поэтому можно еще раз перерисовать табличку.
Итого, наш ответ 1 6 3 5 2 4 7
1746 это некий случайный идентификатор. Он к нашему ответу отношения не имеет.
Когда что-то выполняешь вручную в консоли, результат последней синхронной операции записывается в консоль. Здесь последним был setTimeout, который вернул id созданного таймаута (тот самый, на который можно натравить clearTimeout).
(данный отрывок взял из комментов, спасибо аудитории).
ЗАДАЧА 4
Отлично! и давайте на закрепление, еще одну задачку. Она так сказать с маленькой звездочкой, но не пугайтесь ее.
const myPromise = (delay) => new Promise((res, rej) => { setTimeout(res, delay) })
setTimeout(() => console.log('in setTimeout1'), 1000);
myPromise(1000).then(res => console.log('in Promise 1'));
setTimeout(() => console.log('in setTimeout2'), 100);
myPromise(2000).then(res => console.log('in Promise 2'));
setTimeout(() => console.log('in setTimeout3'), 2000);
myPromise(1000).then(res => console.log('in Promise 3'));
setTimeout(() => console.log('in setTimeout4'), 1000);
myPromise(5000).then(res => console.log('in Promise '));
Итого, у нас сначала есть функция myPromise
, которая принимает параметром время ожидания, а далее конструирует промис, который выполнит функцию через некоторое время ожидания. Этот кусочек кода бояться перестали, идем дальше.
У нас чередуются классические макротаски, с созданными, через функцию myPromise.
Ну ничего страшного, решим.
Также, в момент обновления статьи, я решил, немного дополнить "мой метод объяснения". Вроде бы я сам говорю, давайте на бумажке все распишем, а в итоге один пункт делаю в голове, а именно регистрацию в WEB.API. Возможно для простых задач и ок, но в сложных уже можно если не ошибиться, то не совсем верно объяснить, и как верно подметили в комментах, "натягивать" ответ на решение. Не надо так =).
1. setTimeout(() => console.log('in setTimeout1'), 1000 )
- уходит в Web.Api
WEB.API |
|
Основной поток |
Микрозадачи |
Макрозадачи |
Обращу внимание на то, что пока у нас задачи зарегистрированы в WEB.Api, они не переходят в наши очереди.
const myPromise = (delay) => new Promise((res, rej) => { setTimeout(res, delay) })
myPromise(1000).then(res => console.log('in Promise 1'))
Конструкция new Promise, выполнится сразу же при создании, а значит результатом, будет setTimeout, который сначала пойдет в Web.api, потом станет макротаской, которая в свою очередь породит микрозадачу.
Итого, myPromise(1000) возвращает setTimeout, который сначала надо зарегистрировать в Web.api.
WEB.API |
|
|
Заполним далее. Так как у нас все задачи это setTimeout (на верхнем уровне), то давайте заполним до конца web.Api
res1...4 это функции, которые внутри себя содержат микротаски, но после web.api попадут сначала в очередь макротасок.
WEB.API |
() => console.log('in setTimeout1'), 1000 |
res1, 1000 |
() => console.log('in setTimeout2'), 100 |
res2, 2000 |
() => console.log('in setTimeout3'), 2000 |
res3, 1000 |
() => console.log('in setTimeout4'), 1000 |
res4, 5000 |
Итак, все задачки находятся в web.api. Давайте начнем их исполнять. Первой уходит та, у которой закончилось время простоя, это 'in setTimeout2'
setTimeout(() => console.log('in setTimeout2'), 100)
Она переходит в очередь макрозадач, и так как очередь микротасок и основного потока - пусты, исполняется.
Основной поток |
Микрозадачи |
Макрозадачи |
|
WEB.API |
() => console.log('in setTimeout1'), 1000 |
res1, 1000 |
res2, 2000 |
() => console.log('in setTimeout3'), 2000 |
res3, 1000 |
() => console.log('in setTimeout4'), 1000 |
res4, 5000 |
По факту, исполнение макрозадачи, в нашей системе табличек, можно назвать переходом в основной поток. Так, как у нас посреди решения нашей задачи, нового ничего не приходит, я думаю так сделать законно. Только помним, она уже выполнена. И очередь пуста. Мы это делаем только для того, чтобы потом легко собрать ответ. Давайте пометим ее неким символом, чтобы помнить, что задача уже выполнена.
Основной поток |
Микрозадачи |
Макрозадачи |
|
() => console.log('in setTimeout1'), 1000
res1, 1000
res3, 1000
() => console.log('in setTimeout4'), 1000
Все они переходят в очередь макрозадач.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
WEB.API |
res2, 2000 |
() => console.log('in setTimeout3'), 2000 |
res4, 5000 |
Макрозадачи выполняются по одной. Сначала уходит 'in setTimeout1';
Затем, наступает очередь res1, но помним, что внутри есть исполнения промиса, а это значит что она переходит в очередь микротасок и сразу же там исполняется (реальная очередь основного потока пуста, очередь микротасок пуста).
То же самое будет и с res3. А in setTimeout4' выполнится как обычная макрозадача.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
Да, и сейчас уже можно вспомнить, что res1 => console.log('in Promise 1');
Итого, получаем:
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
Итак, у нас следующая партия задачек выходит из web.api
res2, 2000
() => console.log('in setTimeout3'), 2000
Они обе сначала попадают в очередь макротасок.
Затем res2 (in Promise2) переходит в очередь микротасок, исполняется и затем исполняется 'in setTimeout3'.
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
||
|
||
|
И остается единственная задачка, оставшаяся в web.api
WEB.API |
res4, 5000 |
Когда подходит время ее исполнения, она переходит в очередь макрозадач, тк она единственная во всем списке очередей (не считая исполненных, со смайликом), она выполняется. Переходит из макрозадач - в микрозадачи, и сразу же исполняется.
Итого, мы получаем уже и готовый ответ:
Основной поток |
Микрозадачи |
Макрозадачи |
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
Также, в комментариях, один наш коллега, дал очень классную гифку, которая показывает решение этой задачи. Немного велика скорость, но думаю в сумме с объяснениями выше, сомнений больше быть не должно.
Итого, я очень надеюсь, что подход с табличками будет полезным для junior+, middle разработчиков при прохождении собеседований.
Будет очень круто, если вы покидаете в комменты интересных и сложных задачек по этой теме со своих собесов. Может кто сам собесит и готов поделиться.
P.S. кто знает как таблицы копировать? а то я вручную их все заполнял... Что-то не разобрался.
Комментарии (21)
Alexandroppolus
11.08.2022 00:38+51746 это некий случайный идентификатор. Он к нашему ответу отношения не имеет.
Если кто может более точно объяснить почему он тут появляется, прошу в комментарии.Когда что-то выполняешь вручную в консоли, оно пишет результат последней синхронной операции. Здесь последним был setTimeout, который вернул id созданного таймаута (тот самый, на который можно натравить clearTimeout). Да, это просто число.
Zibx
11.08.2022 01:46+4В продакшене я бы не стал на такое полагаться. Даже на то что два сетТаймаута с одинаковой задержкой выполнятся в порядке их создания — не надо полагаться.
На собеседовании хорошо при таких вопросах отстоять позицию того что есть сейчас, а есть «потом» и это «потом» будет синхронизировано через более надёжные механизмы. Если работодатель настаивает, то можно выполнить код в консоли. Если хочет решения на бумажке, то встать и уйти, нервы дороже.
blindfox
11.08.2022 08:501746 - айди от setTimeout, который можно использовать в clearTimeout, дабы удалить таймер
вообще интересная статья
если интересно, то можешь еще добавить requestAnimationFrame
и + есть подвохи в триггерных кликах https://jsfiddle.net/e5fqrapb/
tishka85
11.08.2022 08:53В 4 задаче не сходится. Все setTimeout в функции myPromise будут идти и регистрироваться синхронно, в потоке основного кода. Соответственно всё что вы занесли в микрозадачи должны по идее быть в макрозадачах. Затем, когда финально собираем ответ:
Срабатывает in 'setTimeout2' через 100 мс
'in setTimeout1' через 1000
Через 1000 мс резолвится первый промис (запускается колбек, который добавляет в очередь микротасок колбек с console.log('in Promise 1'))
Далее цикл событий видит, что в очереди микротасок появилось задание, он тут же его выполняет (console.log('in Promise 1'))
Очередь микротасок пуста, следовательно возвращаемся к макротаскам => Через 1000 мс резолвится второй промис (запускается колбек, который добавляет в очередь микротасок колбек с console.log('in Promise 3'))
Далее цикл событий видит, что в очереди микротасок появилось задание, он тут же его выполняет (console.log('in Promise 3'))
и т.д.
jakut_bmstu Автор
11.08.2022 08:54не совсем понял, что ты имеешь ввиду под словом "не сходится". Порядок выполнения вроде верный.
tishka85
11.08.2022 09:34сейчас попробую объяснить. Просто такое ощущение, что ты не до конца разобрался с этой задачей и в итоге не совсем правильно объяснил последовательность и механику, каким образом этот код будет выполняться (проще говоря "подогнал" ответ под решение). Соответственно, новички, читающие статью, могут либо запутаться в этом примере либо вообще не понять в итоге, как там всё происходит.
Смотри,
По факту, у нас выполнятся все микрозадачи, и они займут свое место в очереди макрозадач
тебя не смутило, что после этой фразы микрозадачи не добавляются по одной в конец очереди макрозадач (как это должно быть и как это было в задаче 2 с console.log(4), ты там сам писал, что она идет в конец очереди макрозадач и это правильно, тут не поспоришь), вместо этого они как бы перемешиваются с уже существующими в очереди макрозадачами, передвигаясь просто вправо.
Ответ прост: ИЗНАЧАЛЬНО все задачи в очереди микрозадач не должны быть в колонке с микрозадачами. Они должны идти в колонке с макрозадачами, потому что как я уже писал:
Все setTimeout в функции myPromise будут идти и регистрироваться синхронно, в потоке основного кода
И только потом, при разборе очереди макрозадач по одной на небольшой промежуток времени эти задачи попадают в список микрозадач (так как резолвится этот промис) и тут же выполняются (так как после каждой макротаски идет выполнение микротасок - при наличии их в очереди). Как раз это я показал в первом комментарии, в своей последовательности (список действий не полный, так как потом происходят аналогичные действия, смысла нет повторять)
jakut_bmstu Автор
11.08.2022 10:20Соглашусь, надо поправить, почему-то действительно биполярочка. Спасибо, что подметил!
jakut_bmstu Автор
11.08.2022 11:38Поправил. Однако знаешь, я вот не до конца понял момент. Ты говоришь, что они срабатывают в основном потоке. Ну тогда, это значит, что после их срабатывания, они должны будут также пойти в конец. А тут получается, что как только создается промис, он сразу уже уходит в макрозадачи, а уже от туда, переходит в микроазадачи.
tishka85
11.08.2022 11:56Ты говоришь, что они срабатывают в основном потоке. Ну тогда, это значит, что после их срабатывания, они должны будут также пойти в конец.
нуу, да) так а что смущает? Если ты имел в виду первый проход по коду и в конец очереди макрозадач, то тут так всё и происходит. Они последовательно и идут в конец очереди макрозадач. Если говорить про проход по макрозадачам и переход в конец очереди микрозадач, то тут также всё логично и прозрачно. Они по одной (в последовательности исходя из задержки в setTimeout) переходят в конец очереди микрозадач (так как очередь пустая, то все они оказываются там всё время единственной задачей) и тут же выполняются.
Кстати, сейчас вроде в статье всё описал как надо)
jakut_bmstu Автор
11.08.2022 12:27вот смотри. все таки я понимаю, что есть у нас недопонимание.
у нас в основном потоке получается все это "промисы";
P1, 1000
P2, 2000
P3, 1000
P, 5000
а в списке макрозадач
ST1, 1000
ST2, 100
ST3, 2000
ST4,1000
И если говорить, что основной поток последовательно пойдет в конец макрозадач, то мы получим
ST1, 1000
ST2, 100
ST3, 2000
ST4,1000
P1, 1000
P2, 2000
P3, 1000
P, 5000
отсортируем по времени задержки
ST2,100
ST1,1000
ST4,1000 ___неверно! (он должен идти после P3)
P1,1000
P3,1000
ST3,2000
P2,2000
P,5000
а вот если мы их сразу будем регистрировать как макрозадачи, то тогда все ок
ST1,1000
P1,1000
ST2,100
P2,2000
ST3,2000
P3,1000
ST4, 1000
P,5000
сортируем:
ST2
ST1
P1
P3
ST4
P2
ST3
Ptishka85
11.08.2022 13:00а в списке макрозадач
ST1, 1000
ST2, 100
ST3, 2000
ST4,1000И если говорить, что основной поток последовательно пойдет в конец макрозадач, то мы получим
ST1, 1000
ST2, 100
ST3, 2000
ST4,1000
P1, 1000
P2, 2000
P3, 1000
P, 5000почему?) ты же последовательно идешь по коду и последовательно добавляешь таски в список макрозадач. Почему у тебя вдруг сначала идут все ST, и потом только все P?
Добавили в список макрозадач ST1
Добавили в список макрозадач P1
Добавили в список макрозадач ST2
Добавили в список макрозадач P2
Добавили в список макрозадач ST3
Добавили в список макрозадач P3
Добавили в список макрозадач ST4
Добавили в список макрозадач P
Затем идем по этому списку макрозадач в последовательности, которая регулируется параметром delay всех setTimeout в этой очереди
jakut_bmstu Автор
11.08.2022 13:10ну да, мой посыл был в том, что мы проходя по коду, их сразу кладем в макрозадачи.
а вот если мы их сразу будем регистрировать как макрозадачи, то тогда все ок
ST1,1000
P1,1000
ST2,100
P2,2000
ST3,2000
P3,1000
ST4, 1000
P,5000сортируем:
ST2
ST1
P1
P3
ST4
P2
ST3
P
Просто формулировка основной поток, она подразумевает сначала выполнение всех задач в основном потоке, потом уже микрозадачи, потом макрозадача, и повторяем. я понял, что вот этот момент что-то не улавливаю до конца. по факту, если у нас код типо такого,
console.log(1)
setTimeout(()=>console.log(2),0)
console.log(3)
То мы согласны, получим 1 3 2
Тк сначала выполнится основной поток, потом макрозадачаDarkspice
11.08.2022 23:55Добрый день. Опечатка небольшая в тексте под 3 задачей:
new Promise(resolve => setTimeout(resolve)).then(()=>console.log(4))
"Тут все ясно понятно. А вот что с четверкой? Микрозадача, порождает макрозадачу, обновим нашу табличку:"
Наверное имелось в виду - "Макрозадача (выполнение колэбэка setTimeout) порождает микрозадачу"
"Получается в момент выполнения микротасок, мы регистрируем макрозадачу, которая потом выполнит микрозадачу. Идем дальше."
Наверное имелось в виду "в момент выполнения executor'а регистрируется макротаска, при выполнении которой регистрируется микротаска"
По поводу ваших комментариев. Вы забываете что сначала setTimeout регистрируется в web api, а потом уже его коллбэк попадает в макротаску.
Вот упрощенная версия того, что происходит в этой задаче.jakut_bmstu Автор
11.08.2022 23:55а что за сервис, позволяющий так посмотреть? или что-то самописное?
jakut_bmstu Автор
11.08.2022 23:59Касаемо третьей задачи, я согласен, выразился я не совсем ясно, и поэтому выглядит как опечатка или ошибка. Спасибо, исправлю.
"в момент выполнения executor'а регистрируется макротаска, при выполнении которой регистрируется микротаска"
именно это я и пытался сказать.
Mox
Полезный текст для прохождения собеседований.
Но, честно говоря, не хочется тащить в прод такой код, где прям нужны такие знания или идет опора в определении последовательность операций именно на то как работает event loop
fransua
Скорее всего он уже в проде внутри реакта/ангуляра/вью
jershell
Эти знания нужны чаще в момент отладки, чтоб можно было объяснить себе и всем заинтересованным почему оно работает именно так. Часто бывает что мы что-то грузим в 3-5 местах и вдруг что-то загружается раньше времени и вот тут как раз понимание ивент лупа очень кстати.