Таймеры, таймауты, EventEmitter в JavaScript и Node.js
ฝัง
- เผยแพร่เมื่อ 11 ก.ย. 2024
- Таймеры: github.com/How...
EventEmitter: github.com/How...
События: github.com/met...
Курс «Основы программирования» с примерами на JavaScript habr.com/ru/po...
#таймеры #eventemitter #асинхронное #программирование #события #nodejs #javascript #js
0:30 callback sync/async
1:35 временная задержка sleep.js
5:35 await-sleep.js
8:40 sleep-then.js
9:30 order.js
18:38 precision.js
22:13 blocking.js
22:50 timers.js
29:35 ref-unref.js
32:05 enroll.js
34:57 eventloop.txt
37:37 eventEmitter
44:32 simple.js
47:48 usage.js
48:30 enhanced.js
50:18 star-fix.js
51:10 usage.js
53:15 closure.js
54:50 fp.js
57:10 methods.js
1:06:35 min.js
1:12:31 prod.js
33:45 Вот доказательство что учить других это самый лучший вид учение)) Хочу сказать что это самый лучший контент по асинхронного программировании в ноде которого я видел, тема углубленное а примеры простые и классные. Спасибо вам за то что вы делаете Тимур Гафарович!
Если кто зашел сюда за EventEmitter, то вам на 37:42
Классный видос. Особенно спасибо за то, что объяснили, как устроен eventemitter, и за то, что показали, как можно одну и ту же функциональность написать в разных стилях
знание - свет, автор - фонарик %)
Очень интересно. Было бы шикарно добавлять тайм-коды:) Подписка и лайк)
Прекрасно!) Спасибо Тимур, как всегда на высоте!
Спасибо, довольно сложная объемная тема...
Слишком затянутое объяснение. Можно было гораздо короче: Лупа и Пупа пошли получать зарплату. Лупа получил за Пупу, а Пупа получил два эвентлупа. Вот и все, теперь вы готовы писать высоконагруженные распределенные системы.
Пусть лучше Пу получит за Лупу .
Кстати хочу заметить что скорость исполнения лямбда функции фибоначи в 6м примере на 16й ноде значительно быстрей чем то что мы видим в видео порядка 1200мс что довольно таки много как по мне -) Интересно посмотреть на нодах ниже в 14 и 18 как вариант!
тут скорее от железа зависит, я наблюдаю разницу в 600мс между пк и ноутом
3-enhanced.js на 49:57 "обмовка" - Array.unshift не забирає елемент із масиву, а додає його в початок.
Согласен, при чем из видео все ясно, а звук уже не исправить
А EventLoop і поток виконання js кода, це два різні потоки чи один і той самий? Тобто коли стек js потока звільнився, то поток eventloop починає підкидувати в стек виконані колбеки з черги тасків, чи я щось не так зрозумів?
Спасибо!
Вообще на практике имхо emit всегда используется отдельно от всего остального (например в агрегатах), и его можно смело делать как emitter.eventName = () => {} через Proxy, задав ему красивый интерфейс в ts)
Добрый вечер, Тимур. Хочу разобраться с работой Event Loop, но просмотрев плейлисты не отыскал релевантного видео у вас на канале. Планируете записать такое видео? Тема интересная в том плане, что общие штуки лупа понятны и их много кто описал, а там где начинаются очереди (таски, микротаски, реквестанимейшнфрейм, рендер) уже запутано. Даже после просмотра докладов Jake Archibald, Erin Zimmer и Philip Roberts на JSConf до конца не разобрался, а на собесах спрашивают + дают мудреные задачи на эту тему
Ну вообще это есть во введении в Node.js, тут th-cam.com/video/mRvzgBGLVyM/w-d-xo.html
А тут гораздо более подробно все смежные темы th-cam.com/users/liveND5HNHicACI?feature=share
@@TimurShemsedinov спасибо, уже смотрю
5:35 await-sleep.js мы там делаем await sleep(3000) внутри асинхронной функции так вот мне интересно имеел ли смысл там ставить await в данном контексте если в слип мы и так ожидаем увидить промис? )
Обязательно, await ждет когда случттся оесолв промиса, иначе исполнение пойдет дальше, без остановки
Тимур, а как быть с таким моментом: при once мы удаляем из массива, а в emit мы этот массив обходим. Отсюда следует, что если мы, например, вначале вызовем once а затем например on или еще раз once, то второй обработчик НЕ ВЫЗОВЕТСЯ, т.к. при отработке первого once из массива уйдет первый элемент, а второй станет первым, соответственно forEach этот второй обработчик перескочит. Нехорошо...
I am a little conffusing. Function g removes himself and on the next line function g call function f. How this is possible? I understand that if I deleted a function, for example, on line 10, this function doesn't exist on line 11.
58:02 Ожидал что once не будет работать, так как мы пытаемся удалить функцию g, а не f. Какая-то магия. Как indexOf ее нашёл?
Понял свою ошибку:) Невнимательность.
💥💥💥
Вот принципиальный вопрос мне не ясен по функц прогр. Здесь как раз в ивент имитере представлены разные подходы к стилю кода , хотя и там и там есть одно замыкание , но на 1:08 пример полностью переписан в функц стиле. Так вот вопрос : я так понял этот пример будет медленее будет работать ? Ну то есть как правило функц стиль ухудшает производительность ? Или это я ошибаюсь ? Или же как вариант это все незначительно ? В общем не понятно тогда как лучше писать - с перемнными или вот так вот цепочкой как на 1:08 .
Есть мнение, что писать библиотеки и подобные им инструменты лучше максимально оптимально, с переиспользованием памяти и максимальной экономией. В то время как пользовательский код может использовать ФП.
Другое дело, если вы увидите, что у вас пользовательский код где-то течёт. Это место, где нужно понять, что не так и сделать его оптимальнее.
"Но не слушайте меня, у меня утром шнурок порвался"
Здравсвуйте.
В строке
if(event) {
event.forEach(fn => fn(...data);
}
как я понял, такую конструкцию надо создавать для того, чтобы в оперативной памяти ос было место, куда записывать еще и аргументы ...data.
Я пробывал упростить код и не создавать массив с одним элементом [fn]. Но это не раблтает. Т.е надо создавать массив [fn], а вариант записать fn в переменную не срабатывает. Что интересно, создается обЬект (или список, что одно и тоже, как я понимаю) с ключами 'name' и значениями, представляющими массивы, но с одним элементом
([fn]).
Я вот голову ломал, как обойтись без массивов, но не придумал пока...
С EventEmitter вроде было понятно в начале, но как-то быстро потерялась нить событий у меня в голове, что откуда и куда )))
Как все эти связи можно удержать в памяти?
25 лет тренировки
@@TimurShemsedinov В EventEmitter методы on и emit имеют переменную event, объявление которой можно избежать, при этом поведение не изменится, по крайней мере в этом примере. Особенно в методе on при первом взгляде появляется ощущение, что мы обращаемся не к объекту по ссылке, а к отдельной переменной. Например,
EventEmitter.prototype.on = function(name, fn) {
if (this.events[name]) {
this.events[name].push(fn);
} else {
this.events[name] = [fn];
}
@@TheSupermaniaco В вашем примере появляется дублирование кода, два подряд обращения к this.events[name] мы получаем массив в ифе и теряем ссылку на него, потом для пуша опять получаем ссылку на массив. С переменной гораздо лучше, меньше кода дублируется.
@@TimurShemsedinov Благодарю. Тем не менее многие авторы в том числе и вы пропагандируют писать понятный код пусть и не оптимальный - зависит от задачи. Тут мы потеряем немного памяти, только в if, но интересно насколько это действительно полезно использовать переменную? Может есть пример из опыта?
Я практически уверен, что человек из комментария выше запутался именно в этом месте)
@@TheSupermaniaco память выделяется под значение переменные бесплатные
Тайминг EventEmitter - th-cam.com/video/LK2jveAnRNg/w-d-xo.html
Хорошо бы привести более-менее реальные случаи, когда использование EventEmitter оправдано.
Во многих последующих лекциях, особенно по node.js он пртменяется. Смотрите дальше
@@TimurShemsedinov Я просмотрел несколько лекций, выбирал те, которые мне были интересны. Пока ещё не встретил 🙂. У меня не стоит цели просмотреть всё в ближайшее время, хотя они, безусловно, очень занимательные и глубоко погружают в тему. Всегда приятно, если удаётся узнать новые аспекты, казалось бы, давно знакомого материала.
@@TimurShemsedinov Всплыл ролик в рекомендациях от JSNinja про EventEmitter. Ну как я и предполагал, он сам же говорит, что это в основном используется для отладки и логирования.
Иначе зачем ещё в приложение на условном socket.io запихивать EE
@@AlbertMaximov socket.io это устаревшая ересь и пучок говнокода
@@AlbertMaximov пример th-cam.com/video/RbhYxygxroc/w-d-xo.html
Пример 9 - имхо, как НЕЛЬЗЯ писать код. Можно было еще через обфускатор пропустить :)
Конечно нельзя, это все, чтоб люди српвнили подходы)
@@TimurShemsedinov Но здесь есть такие, которые без Ваших комментариев не могут самостоятельно при всех предложенных к рассмотрению вариантах выбрать рабочие. Мне вот именно этого в Ваишх замечательных лекциях и не хватает. Хотелось чтобы Вы больше себя добавили в материал и добавляли собственное мнение, что и когда стоит (или не стоит) использовать.
@@318307able нужно изучать все варианты, потому, что в реальных проектах код не всегда самый лучший, а как я бы писал, просто берите более сложные лекции по ноде, по архитектуре и там уже есть мои решения, но нет одного правильного на все случаи жизни, в разных случаях и я по-разному пишу
@@TimurShemsedinov Да, я понимаю. Но иногда вот этих связей с общей картиной и не хватает. Чтобы Вы объяснили когда, что и зачем использовать.
Хотя этот, как мне кажется, недостаток, просто мизер с той пользой, которую Вы несете своими лекциями. Огромное спасибо!)
@@318307able каждую тему приходится 2-3 раза проходить, сначала на простом уровне, а потом усложнять, там по оглавлению курсов всегда так, если не продвинуться по другим темам, то нельзя все сразу по одной в одну лекцию запихнуть, она и длинная будет и непонятная,
в чем разница между timer.unref() и clearTimeout(timer) ?
Разобрался.
Для тех кому тоже интересно:
К примеру такой код.
setTimeout(() => {
console.log('Bye!');
}, 5000)
const timer = setInterval(() => {
console.log(process.memoryUsage());
}, 1000)
Каждую секунду будет печататься memoryUsage. Это продолжится даже тогда, когда setTimeout отработает.
Второй вариант:
setTimeout(() => {
console.log('end');
}, 5000)
const timer = setInterval(() => {
console.log(process.memoryUsage());
}, 1000)
timer.unref();
Каждую секунду будет печататься memoryUsage. И напечатается 5 раз. Когда setTimeout отработает, приложение завершится, так как timer уже не будет требовать чтобы event loop продолжала работу.
Третий вариант:
setTimeout(() => {
console.log('end');
}, 5000)
const timer = setInterval(() => {
console.log(process.memoryUsage());
}, 1000)
clearInterval(timer)
memoryUsage не напечатается ни разу. Скрипт завершится через 5 секунд.
unref не удаляет обработчик события, а делает так, чтобы это событие не держало процесс, т.е. если стек опустошается, то процесс выходит, не дожидаясь события. Это работает только для ноды, но не для браузера.
@@TimurShemsedinov спасибо, Тимур! Уложилось в голове.
А можно ссылки на репозиторий где можно склонить код?
В описании к видео
я тоже люблю closure, но меня за єто не любят (( Что делать?
однажди я виполнил простое тестовое. функция возвращала обьект из замикания. "Что єтим хотел сказать кандидат? Код не кроссбраузерний! Код нечитаемий!" А код продолжал упорно работать везде. Пришлось для резюмиста полдня писать комменти с обьяснениями. Но отношения били безнадежн испорчени )) Может надо жить на прототайпах...? Может наш мир - ООП?
Наш мир мультипарадигменный, живем на смешении всего и парадигмы для нас - это способ строить абстракции и делать понятный и удобный синтаксис
@@TimurShemsedinov Забей на цель, живи реализацией! ))
@@romankotenko7 ну почему же, цель важна, наша цель - это безклассовое общество, построенное на базе научного метода и общественная собственность на средства производства, но парадигмы это ни в коем случае не про цель
@@TimurShemsedinov Ким Чен Ын, к доске, тяните билет.
@@TimurShemsedinov вот за этот комментарий респектище последний ваш) но надо за эту идею нам всем бороться
как же туго ты всё объясняешь...
может ты тугой?)
@@spir1tfly чувак подписан на "WebDev с нуля. Канал Алекса Лущенко", тут всё ясно, странно что нету подписки на хауди хо)