TGViewer
melikhov.dev melikhov.dev @melikhov_dev · 4.74K subscribers
Post #187 4.57K
Сегодня полдня спорили JS синхронный или асинхроннный. Так вот, совершенно не важно, как вы его называете, важно другое — понимание, как работает рантайм, в котором ваш JS запущен. Да, сам язык ECMAScript не обладает встроенными асинхронными апишками (ок, мне тут говорят про Атомики. Поговорим когда они будут везде!). Всё, что вы делаете в нём происходит синхронно. Максимум можно отбросить что-то в очередь микротасок — таким образом мы поменяем порядок обработки, но не освободим Event Loop. Цепочка из коллбеков вручную созданных промисов так и останется крутиться в фазе микротасков. Следующая итерация внешнего event loop не наступит. Из коробки мы не можем сказать «Эй VM, вот тебе корутина, выполни её в соседнем треде и верни результат по готовности». Нет у нас ничего для этого. Мы можем очень сильно упороться и написать свой Event Loop с прерываниями внутри JS — вот это мы можем да.

Таймеры, setImmidiate, функции, возвращающие промисы — всё это прилетает к нам из окружения. Именно платформа, где мы запускаем наш JS предоставляет работу с другими тредами и даёт нам EventLoop. В спецификации самого ECMAScript нет никаких таймеров и фечей — всё это внешние апишки. Есть отдельные ребята, попавшие в спеку — например, динамические импорты. Но их тоже крутит внешний рантайм, не сам движок JS.

Как работает код на node.js?

Мы выполняем небольшой синхронный код на старте и заряжаем задачи во внешние API. Например, задачу слушать какой-то порт. К это задаче мы привязываем коллбек. Дальше где-то во внешнем мире другой код, написанный на другом языке (на плюсах, например), в другом треде слушает порты. Между внешним миром и нашим JS-кодом крутится эвент луп. Он проверяет, не сработал ли триггер и вызывает соответствующий коллбек в JS. Коллбек снова синхронно выполняется (и может поставить новые задачи в планировщик). Коллбек это реакция на то, что во внешнем мире что-то произошло. Что случится, если коллбек выполняется слишком долго? Например, мы запустили очень большой цикл? Event loop будет стоять и ждать выполнения этой синхронной операции. Ничего не будет происходить. Никакие внешние запросы не будут обработаны, никакие таймеры не сработают. В нашем Event Loop возникнет лаг.

Для Node.js приложения это значит, что в этот момент конкретно этот экземпляр приложения будет тормозить для всех клиентов. Т.е. если у вас есть один медленный эндпоинт, то обращение к нему остановит обработку для всех остальных эндпоинтов. Из-за одного пользователя будут страдать все остальные. Именно потому долгие синхронные операции в Node.js максимально нежелательны. Если вы пишете консольный скрипт или стартуете приложение — вы можете делать что-то синхронно. Если же делаете обработчик запроса пользователя, то добро пожаловать в асинхронность.

Да, нам нужно превращать синхронные операции в асинхронные. Встроенных средств в языке для этого нет, но есть во внешней среде: таймеры и setImmidiate, например. Мы можем буквально сказать — выполни этот код в следующем цикле. Или, иначе говоря, «вызови коллбек когда внешний таймер сработает через 0ms (т.е. в следующем цикле)». Маленькие кусочки нашего синхронного кода будут вызываться по чуть-чуть и мы дадим Event loop время размотать накопившиеся очереди и вызвать другие коллбеки.

А как померить лаг? Мы же должны следить за ним. Ну, конечно, мы можем взять встроееный метод perf_hooks.monitorEventLoopDelay . Но давайте подумаем, как это можно сделать на коленке? Очень просто! Берём текущий таймстамп в высоком разрешении, вызываем setTimeout(fn, 0) и в его коллбеке снимаем таймстамп и измеряем разницу. Время, через которое сработает коллбек таймера с ожидаемо нулевой задержкой и есть наш EventLoop-лаг.

Итого, мы действительно пишем асинхронный код каждый день. И эту замечательную асинхронность нам даёт рантайм, котором наш JS запущен. Этот рантайм содержит и интерпретатор языка и EventLoop и работу с I/O. Потому Нода это не просто V8, это V8 + libuv. А Deno это V8 + ядро на Rust + Tokio.
Telegram artalog Давайте пжлст договоримся. EcmaScript (ES) - это спека, в ней нет ничего про таймеры и остальное IO. Но смысла в ней в отдельности от рантайма практически нет. JavaScript (JS) - это ES + IO апишки, типа таймеров, фетча, бродкаст чанклов и т.п. Это то с…
  • 🔥 48
  • 👍 9
  • 😁 1
More from @melikhov_dev
  1. Sep 27, 2026https://www.aymannadeem.com/artificial/intelligence,/developer/tools/2026/09/24/plan-mode-…
  2. Sep 26, 2026Блин, ну нравятся мне TUI решения, сил нет. Просто, красиво и понятно (для меня). Продолжа…
  3. Sep 13, 2026Какой он — личный харнес? Вот мы и пришли в точку, когда уже бизнес не устраивает медленна…
  4. Aug 30, 2026Разобрал своего питонячего новостного бота и собрал нового, уже на Гермесе. Ну как собрал…
  5. Aug 24, 2026Вы могли наверное заметить что как-то мало меня стало в последнее время. Не видно на конфе…
  6. Aug 6, 2026Как же хорошо перечитывается сейчас «Трилогия Муравейника» Гибсона (она же Sprawl trilogy)…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →