Сегодня мы поговорим про модуль async_hooks и, в частности, класс AsyncLocalStorage (ALS), который недавно в нем появился. Это CLS (Continuation Local Storage) API, который имеет шансы вскоре выйти из экспериментального статуса (в отличие от самих async_hooks).
Начнем мы с простого примера использования ALS. Предположим, что мы хотим добавить id запроса во все сообщения журнала (log), с ним связанные. Самое простое решение - передавать контекст между всеми нашими модулями.
Но программисты народ ленивый (в хорошем смысле) и всегда пытаются уменьшить связность модулей и кол-во кода на сферическую фичу в вакууме. На помощь приходит ALS, позволяющий ассоциировать контекст с асинхронной цепочкой вызовов. Вот как это выглядит в случае с Fastify plugin.
Думаю те, кто работал с ThreadLocal в Java и AsyncLocal в .NET, увидели сходство. То, что было давно доступно в других runtime, в Node.js core появилось только в этом году после неоднократных обсуждений в TSC.
Что же было в экосистеме до появления ALS? Это были разнообразные user-land модули, самыми известными из которых были continuation-local-storage (отсюда аббревиатура - CLS) и его наследник cls-hooked. Их API во многом повлиял на ALS.
Любопытно, что оригинальный CLS был основан на древнем process.addAsyncListener API, который доступен только в Node.js v0.11, и его polyfill, реализованном за счет monkey patch'ей релевантных core API. А cls-hooked уже работал на async_hooks.