F5 — Concurrencia en Node.js
Lo que necesitas dominar: single-thread real de JS vs thread pool de libuv, fases del event loop, microtasks vs macrotasks, y cuándo usar Promise.all frente a sus alternativas. Mismo modelo mental que F1 (concurrencia Python) — runtime distinto, misma pregunta de fondo: ¿qué bloquea y qué no?
Videos y charlas (empieza por acá)
What the heck is the event loop anyway? — Philip Roberts (JSConf EU 2014)
Gratis · ~27 min · La charla de referencia del event loop en JavaScript — call stack, web APIs, callback queue, visualizado en vivo. No es específica de Node (nace del lado browser) pero el modelo mental es el mismo que corre por debajo de cualquier runtime JS.
Node’s Event Loop From the Inside Out — Sam Roberts, IBM (Node.js Interactive 2016)
Gratis · ~30 min · Esta sí es específica de Node: libuv, thread pool, las fases reales del loop (timers/poll/check), con pseudocódigo en C para quien quiere ver qué pasa por debajo del runtime.
Docs y referencia
- Node.js Learn — The Node.js Event Loop · gratis — la guía oficial: fases del loop, timers,
process.nextTick()vs microtasks de Promise. Para consultar cuando te trabes con el orden exacto de ejecución. - libuv — Design overview · gratis — la documentación de la librería C que hace el trabajo pesado por debajo de Node: el thread pool, el I/O loop, qué usa cada uno.
- MDN — Promise.all() · gratis — referencia oficial: comportamiento fail-fast, orden de resultados, y de ahí mismo los links a
allSettled/race/anypara cuandoPromise.allno es lo que necesitás.
Puente con lo que ya sabés (Python/asyncio)
Si venís de asyncio: es el mismo modelo — single-thread, cooperativo, un await/.then cede el control — pero Node lo tiene desde el diseño original del runtime (no como librería añadida) y organiza el trabajo en fases explícitas (timers → poll → check) en vez de una sola cola genérica. Promise.all es el análogo directo de asyncio.gather: mismo fail-fast, misma idea de fan-out concurrente.
| Node | Python asyncio | |
|---|---|---|
| Paralelismo real | Thread pool de libuv (fs, DNS, crypto) | multiprocessing (CPU-bound) |
| Fan-out concurrente | Promise.all | asyncio.gather / TaskGroup |
| Si uno falla | Promise.all rechaza ya (fail-fast) | gather no cancela nada por default; TaskGroup cancela todo |
Para que no se quede en video
Tomá cualquier endpoint Node/Express/NestJS que ya tengas — metele a propósito un loop síncrono pesado (ordenar un array grande) dentro de un handler y medí cómo se frenan TODAS las conexiones abiertas, no solo esa request. Después arreglalo sacando el trabajo a un worker_thread o una cola de jobs. Es la misma lección que F1 con el GIL, del otro lado del runtime.