поток | web dev | it
5 subscribers
36 photos
1 video
1 file
40 links
логи моего бесконечного обучения

оповещалка о стримах, можно общаться => https://t.me/it_flow_chat

legacy docs: t.me/faustdoc
github: github.com/Faustze
twitch: twitch.tv/Faustze
Download Telegram
RegExp шпаргалка + теория + задачи

https://notes.faustze.tech/leetcode/regexp

#leetcode #regexp
на память
Vue 3 Reactivity Internals

Proxy, WeakMap, effect tracking

#vue
Vue_Compiler.png
1.8 MB
Vue 3 Compiler Internals

Template → render function → vdom

#vue
Почему одна бесконечная рекурсия вешает вкладку, а другая нет: event loop, микро- и макрозадачи, rAF

Бесконечный .then() замораживает вкладку. Бесконечный requestAnimationFrame крутится сутками, и браузеру норм:
function a() { Promise.resolve().then(a) }
function b() { requestAnimationFrame(b) }
function c() { setTimeout(c, 0) }


Все три колбэка бесконечные, все три через очередь. Убивает вкладку только первая

Event loop сам по себе ничего не выполняет. Он диспетчер: смотрит, освободился ли стек вызовов, и если да, то берёт из очереди следующий колбэк и кладёт туда. Очередей у него несколько, и разбирает он их по-разному. Вот в этом «по-разному» весь ответ

Порядок одного прохода

синхронный код
→ микрозадачи (.then, await, queueMicrotask, MutationObserver) - все до единой
→ кадр: rAF → стили и layout → ResizeObserver → IntersectionObserver → отрисовка
→ ровно одна задача (setTimeout, клик, сеть)
→ и заново


Микрозадачи исполняются до конца.
Условие «очередь пуста» диспетчер проверяет перед каждым шагом, поэтому микрозадача, которая по ходу дела положила в очередь ещё одну, успевает в тот же самый проход. a кладёт следующую a, та - следующую, и поэтому очередь никогда не опустошится. До кадра и до клика дело просто не доходит: вкладка заморозилась

У этой ненасытности есть причина: Промисы и await должны исполняться как единый непрерывный блок относительно остального кода - иначе между шагами await во вкладку просачивались бы чужие события и рендер с промежуточным, ещё не готовым состоянием. Атомарность микрозадач - то, на чём держится вся семантика async/await

queueMicrotask(fn) кладёт колбэк в ту же самую очередь, что и .then(). Разница в том, что Promise.resolve().then(fn) создаёт лишний промис ради побочного эффекта, а queueMicrotask говорит то же самое напрямую


Macrotask берётся ровно одна.
Одна - и диспетчер свободен. c плодит новые точно так же бесконечно, но между двумя c браузер успевает все свои дела, поэтому вкладка живая

Честного нуля в setTimeout(c, 0) при этом нет. Глубже пятого уровня вложенности браузер начинает подставлять минимальную задержку около 4 мс - защита ровно от такого рекурсивного злоупотребления таймером. c крутится с этим полом

Кадр браузер собирает заранее. Список колбэков копируется до того, как браузер начнёт их выполнять. Всё, что зарегистрируешь через requestAnimationFrame уже внутри этого прохода, физически в него не попадёт - уедет в следующий кадр. Поэтому рекурсия через rAF и есть штатный способ анимировать: она сама себя режет по кадрам. Мне эта часть нравится больше всего

К кадру привязаны и наблюдатели. Сразу после колбэков rAF браузер пересчитывает стили и layout и тут же раздаёт колбэки ResizeObserver, а перед самой отрисовкой обновляет наблюдения IntersectionObserver. Колбэки intersection не лежат в общей очереди задач рядом с кликом и таймером - их ставит сама фаза кадра, отдельным шагом после ResizeObserver

Как дробить тяжёлую работу

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

Рекурсия на .then() для этого не подходит вообще: она управление не отдаёт, а забивает микроочередь и держит браузер до последнего. Резать нужно через очередь задач - там между кусками у браузера есть окно.

Инструментов два, и выбор между ними - это вопрос «когда доделать»:
- setTimeout(fn, 0) - если остаток работы нужен скоро и ждать нельзя
- requestIdleCallback(fn) - если он терпит и может подождать момента, когда браузеру нечем заняться

Красиво тут то, что получается симметрия с rAF. Все три - способ сказать «разбуди меня в нужный момент», просто моменты разные: rAF ловит «пора рисовать кадр», idle callback - «дел больше нет», таймер - «прошло столько-то миллисекунд».

п.с. Цикл на микрозадачах держится только на условии остановки внутри самого колбэка, снаружи его не подстрахует никто. У задач и у rAF страховка вшита в саму очередь - это граница прохода.


Мои заметки по теме;

HTML Standard: event loops


#js
Forwarded from Вайб-кодинг
Media is too big
VIEW IN TELEGRAM
Бесплатный 30-минутный курс по памяти в агентных системах от бывшего инженера Google.

0:00 — почему каждый вызов LLM начинается с амнезии
2:31 — хранение памяти в тексте, таблицах или графах
5:04 — четыре способа поиска — ничего не делать, ключевые слова, RAG, Graph RAG
7:29 — поддержка памяти — добавление, удаление, retire, attribution, reflection
9:47 — собираем всё на обычном тексте и SQLite
13:13 — добавляем векторное хранилище только тогда, когда оно действительно нужно
14:38 — память в строках, графовая память и временной граф
21:03 — запускаем код для всех пяти вариантов
Please open Telegram to view this post
VIEW IN TELEGRAM