[{"data":1,"prerenderedAt":2922},["ShallowReactive",2],{"page-\u002Fjs\u002F15-callbacks-and-the-event-loop":3},{"id":4,"title":5,"body":6,"description":2915,"extension":2916,"meta":2917,"navigation":228,"path":2918,"seo":2919,"stem":2920,"__hash__":2921},"content\u002Fjs\u002F15-callbacks-and-the-event-loop.md","JavaScript 15 — Event Loop Internals: Call Stack, Microtasks, Macrotasks & Rendering",{"type":7,"value":8,"toc":2904},"minimark",[9,14,19,436,440,678,682,1317,1323,1632,1636,2012,2016,2356,2360,2734,2738,2742,2844,2900],[10,11,13],"h1",{"id":12},"_15-event-loop-internals-call-stack-microtasks-macrotasks-rendering","15 — Event Loop Internals: Call Stack, Microtasks, Macrotasks & Rendering",[15,16,18],"h2",{"id":17},"the-event-loop-model","The Event Loop Model",[20,21,23],"code-wrapper",{"language":22},"javascript",[24,25,29],"pre",{"className":26,"code":27,"language":22,"meta":28,"style":28},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F ── Single-threaded JS: one call stack, one event loop, one heap ──\n\u002F\u002F\n\u002F\u002F   ┌──────────────────┐\n\u002F\u002F   │  Call Stack       │  ← LIFO — function frames (pushed\u002Fpopped as functions call\u002Freturn)\n\u002F\u002F   │  [main()]         │\n\u002F\u002F   │  [outer()]        │\n\u002F\u002F   │  [inner()]  ← top │  ← always executes the top frame\n\u002F\u002F   └──────────────────┘\n\u002F\u002F\n\u002F\u002F   ┌──────────────────┐     ┌───────────────────────┐\n\u002F\u002F   │  Heap (memory)    │     │  Web\u002FNode APIs (C++)  │\n\u002F\u002F   │  objects, closures│     │  setTimeout, fetch,   │\n\u002F\u002F   │  (GC managed)     │     │  DOM, I\u002FO, crypto     │\n\u002F\u002F   └──────────────────┘     └───────────┬───────────┘\n\u002F\u002F                                         │ (callback ready)\n\u002F\u002F   ┌─────────────────────────────────────▼───────────────────┐\n\u002F\u002F   │                  Event Loop (one iteration = one \"tick\")  │\n\u002F\u002F   │                                                            │\n\u002F\u002F   │  1. Pick ONE macrotask from the macrotask queue            │\n\u002F\u002F   │     → setTimeout, setInterval, I\u002FO, UI events              │\n\u002F\u002F   │                                                            │\n\u002F\u002F   │  2. Drain the microtask queue (ALL microtasks)             │\n\u002F\u002F   │     → Promise.then\u002Fcatch\u002Ffinally, queueMicrotask           │\n\u002F\u002F   │     → new microtasks added during step 2 also run NOW      │\n\u002F\u002F   │                                                            │\n\u002F\u002F   │  3. Render (browser only):                                 │\n\u002F\u002F   │     → requestAnimationFrame callbacks                     │\n\u002F\u002F   │     → style\u002Flayout calculation                            │\n\u002F\u002F   │     → paint                                               │\n\u002F\u002F   │                                                            │\n\u002F\u002F   │  4. Go back to step 1 (next tick)                         │\n\u002F\u002F   └────────────────────────────────────────────────────────────┘\n\n\u002F\u002F ── Execution order demonstration ──\nconsole.log(\"1: script start (synchronous)\");\n\nsetTimeout(() => console.log(\"5: macrotask (setTimeout)\"), 0);\n\nPromise.resolve()\n    .then(() => console.log(\"3: microtask (Promise.then)\"))\n    .then(() => console.log(\"4: microtask (chained .then)\"));\n\nqueueMicrotask(() => console.log(\"2: microtask (queueMicrotask)\"));\n\nconsole.log(\"6: script end (synchronous)\");\n\n\u002F\u002F Output order: 1, 6, 2, 3, 4, 5\n\u002F\u002F 1, 6: synchronous (script is a macrotask — runs first)\n\u002F\u002F 2, 3, 4: microtasks (drained after script, before next macrotask)\n\u002F\u002F 5: macrotask (setTimeout — runs after all microtasks drained)\n","",[30,31,32,41,47,53,59,65,71,77,83,88,94,100,106,112,118,124,130,136,142,148,154,159,165,171,177,182,188,194,200,206,211,217,223,230,236,257,262,294,299,314,339,362,367,388,393,407,412,418,424,430],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sdCPZ","\u002F\u002F ── Single-threaded JS: one call stack, one event loop, one heap ──\n",[33,42,44],{"class":35,"line":43},2,[33,45,46],{"class":39},"\u002F\u002F\n",[33,48,50],{"class":35,"line":49},3,[33,51,52],{"class":39},"\u002F\u002F   ┌──────────────────┐\n",[33,54,56],{"class":35,"line":55},4,[33,57,58],{"class":39},"\u002F\u002F   │  Call Stack       │  ← LIFO — function frames (pushed\u002Fpopped as functions call\u002Freturn)\n",[33,60,62],{"class":35,"line":61},5,[33,63,64],{"class":39},"\u002F\u002F   │  [main()]         │\n",[33,66,68],{"class":35,"line":67},6,[33,69,70],{"class":39},"\u002F\u002F   │  [outer()]        │\n",[33,72,74],{"class":35,"line":73},7,[33,75,76],{"class":39},"\u002F\u002F   │  [inner()]  ← top │  ← always executes the top frame\n",[33,78,80],{"class":35,"line":79},8,[33,81,82],{"class":39},"\u002F\u002F   └──────────────────┘\n",[33,84,86],{"class":35,"line":85},9,[33,87,46],{"class":39},[33,89,91],{"class":35,"line":90},10,[33,92,93],{"class":39},"\u002F\u002F   ┌──────────────────┐     ┌───────────────────────┐\n",[33,95,97],{"class":35,"line":96},11,[33,98,99],{"class":39},"\u002F\u002F   │  Heap (memory)    │     │  Web\u002FNode APIs (C++)  │\n",[33,101,103],{"class":35,"line":102},12,[33,104,105],{"class":39},"\u002F\u002F   │  objects, closures│     │  setTimeout, fetch,   │\n",[33,107,109],{"class":35,"line":108},13,[33,110,111],{"class":39},"\u002F\u002F   │  (GC managed)     │     │  DOM, I\u002FO, crypto     │\n",[33,113,115],{"class":35,"line":114},14,[33,116,117],{"class":39},"\u002F\u002F   └──────────────────┘     └───────────┬───────────┘\n",[33,119,121],{"class":35,"line":120},15,[33,122,123],{"class":39},"\u002F\u002F                                         │ (callback ready)\n",[33,125,127],{"class":35,"line":126},16,[33,128,129],{"class":39},"\u002F\u002F   ┌─────────────────────────────────────▼───────────────────┐\n",[33,131,133],{"class":35,"line":132},17,[33,134,135],{"class":39},"\u002F\u002F   │                  Event Loop (one iteration = one \"tick\")  │\n",[33,137,139],{"class":35,"line":138},18,[33,140,141],{"class":39},"\u002F\u002F   │                                                            │\n",[33,143,145],{"class":35,"line":144},19,[33,146,147],{"class":39},"\u002F\u002F   │  1. Pick ONE macrotask from the macrotask queue            │\n",[33,149,151],{"class":35,"line":150},20,[33,152,153],{"class":39},"\u002F\u002F   │     → setTimeout, setInterval, I\u002FO, UI events              │\n",[33,155,157],{"class":35,"line":156},21,[33,158,141],{"class":39},[33,160,162],{"class":35,"line":161},22,[33,163,164],{"class":39},"\u002F\u002F   │  2. Drain the microtask queue (ALL microtasks)             │\n",[33,166,168],{"class":35,"line":167},23,[33,169,170],{"class":39},"\u002F\u002F   │     → Promise.then\u002Fcatch\u002Ffinally, queueMicrotask           │\n",[33,172,174],{"class":35,"line":173},24,[33,175,176],{"class":39},"\u002F\u002F   │     → new microtasks added during step 2 also run NOW      │\n",[33,178,180],{"class":35,"line":179},25,[33,181,141],{"class":39},[33,183,185],{"class":35,"line":184},26,[33,186,187],{"class":39},"\u002F\u002F   │  3. Render (browser only):                                 │\n",[33,189,191],{"class":35,"line":190},27,[33,192,193],{"class":39},"\u002F\u002F   │     → requestAnimationFrame callbacks                     │\n",[33,195,197],{"class":35,"line":196},28,[33,198,199],{"class":39},"\u002F\u002F   │     → style\u002Flayout calculation                            │\n",[33,201,203],{"class":35,"line":202},29,[33,204,205],{"class":39},"\u002F\u002F   │     → paint                                               │\n",[33,207,209],{"class":35,"line":208},30,[33,210,141],{"class":39},[33,212,214],{"class":35,"line":213},31,[33,215,216],{"class":39},"\u002F\u002F   │  4. Go back to step 1 (next tick)                         │\n",[33,218,220],{"class":35,"line":219},32,[33,221,222],{"class":39},"\u002F\u002F   └────────────────────────────────────────────────────────────┘\n",[33,224,226],{"class":35,"line":225},33,[33,227,229],{"emptyLinePlaceholder":228},true,"\n",[33,231,233],{"class":35,"line":232},34,[33,234,235],{"class":39},"\u002F\u002F ── Execution order demonstration ──\n",[33,237,239,243,247,250,254],{"class":35,"line":238},35,[33,240,242],{"class":241},"ssxIu","console.",[33,244,246],{"class":245},"sIsaT","log",[33,248,249],{"class":241},"(",[33,251,253],{"class":252},"sJ6F3","\"1: script start (synchronous)\"",[33,255,256],{"class":241},");\n",[33,258,260],{"class":35,"line":259},36,[33,261,229],{"emptyLinePlaceholder":228},[33,263,265,268,271,275,278,280,282,285,288,292],{"class":35,"line":264},37,[33,266,267],{"class":245},"setTimeout",[33,269,270],{"class":241},"(() ",[33,272,274],{"class":273},"svdQ7","=>",[33,276,277],{"class":241}," console.",[33,279,246],{"class":245},[33,281,249],{"class":241},[33,283,284],{"class":252},"\"5: macrotask (setTimeout)\"",[33,286,287],{"class":241},"), ",[33,289,291],{"class":290},"snvgF","0",[33,293,256],{"class":241},[33,295,297],{"class":35,"line":296},38,[33,298,229],{"emptyLinePlaceholder":228},[33,300,302,305,308,311],{"class":35,"line":301},39,[33,303,304],{"class":290},"Promise",[33,306,307],{"class":241},".",[33,309,310],{"class":245},"resolve",[33,312,313],{"class":241},"()\n",[33,315,317,320,323,325,327,329,331,333,336],{"class":35,"line":316},40,[33,318,319],{"class":241},"    .",[33,321,322],{"class":245},"then",[33,324,270],{"class":241},[33,326,274],{"class":273},[33,328,277],{"class":241},[33,330,246],{"class":245},[33,332,249],{"class":241},[33,334,335],{"class":252},"\"3: microtask (Promise.then)\"",[33,337,338],{"class":241},"))\n",[33,340,342,344,346,348,350,352,354,356,359],{"class":35,"line":341},41,[33,343,319],{"class":241},[33,345,322],{"class":245},[33,347,270],{"class":241},[33,349,274],{"class":273},[33,351,277],{"class":241},[33,353,246],{"class":245},[33,355,249],{"class":241},[33,357,358],{"class":252},"\"4: microtask (chained .then)\"",[33,360,361],{"class":241},"));\n",[33,363,365],{"class":35,"line":364},42,[33,366,229],{"emptyLinePlaceholder":228},[33,368,370,373,375,377,379,381,383,386],{"class":35,"line":369},43,[33,371,372],{"class":245},"queueMicrotask",[33,374,270],{"class":241},[33,376,274],{"class":273},[33,378,277],{"class":241},[33,380,246],{"class":245},[33,382,249],{"class":241},[33,384,385],{"class":252},"\"2: microtask (queueMicrotask)\"",[33,387,361],{"class":241},[33,389,391],{"class":35,"line":390},44,[33,392,229],{"emptyLinePlaceholder":228},[33,394,396,398,400,402,405],{"class":35,"line":395},45,[33,397,242],{"class":241},[33,399,246],{"class":245},[33,401,249],{"class":241},[33,403,404],{"class":252},"\"6: script end (synchronous)\"",[33,406,256],{"class":241},[33,408,410],{"class":35,"line":409},46,[33,411,229],{"emptyLinePlaceholder":228},[33,413,415],{"class":35,"line":414},47,[33,416,417],{"class":39},"\u002F\u002F Output order: 1, 6, 2, 3, 4, 5\n",[33,419,421],{"class":35,"line":420},48,[33,422,423],{"class":39},"\u002F\u002F 1, 6: synchronous (script is a macrotask — runs first)\n",[33,425,427],{"class":35,"line":426},49,[33,428,429],{"class":39},"\u002F\u002F 2, 3, 4: microtasks (drained after script, before next macrotask)\n",[33,431,433],{"class":35,"line":432},50,[33,434,435],{"class":39},"\u002F\u002F 5: macrotask (setTimeout — runs after all microtasks drained)\n",[15,437,439],{"id":438},"microtask-queue-full-drain-semantics","Microtask Queue: Full Drain Semantics",[20,441,442],{"language":22},[24,443,445],{"className":26,"code":444,"language":22,"meta":28,"style":28},"\u002F\u002F ── The microtask queue is FULLY drained before the next macrotask ──\n\u002F\u002F New microtasks added during the drain ALSO run in the same drain (no limit).\n\nPromise.resolve().then(() => {\n    console.log(\"A\");\n    Promise.resolve().then(() => console.log(\"B\"));  \u002F\u002F added during drain — runs NOW\n});\nPromise.resolve().then(() => console.log(\"C\"));\nconsole.log(\"D\");\n\u002F\u002F Output: D, A, C, B\n\u002F\u002F D: synchronous\n\u002F\u002F A: first microtask (queued before D finished)\n\u002F\u002F C: second microtask (queued at the same time as A)\n\u002F\u002F B: added during A's execution → runs in the SAME drain (after C, before next macrotask)\n\n\u002F\u002F ── Microtask starvation: infinite microtasks block macrotasks forever ──\n\u002F\u002F (Don't run this — it blocks the event loop)\n\u002F\u002F function infinite() {\n\u002F\u002F     Promise.resolve().then(infinite);\n\u002F\u002F }\n\u002F\u002F infinite();\n\u002F\u002F setTimeout(() => console.log(\"never\"), 0);  \u002F\u002F never runs — microtask queue never empties\n\n\u002F\u002F ── Node.js: process.nextTick vs Promise microtask ──\n\u002F\u002F process.nextTick has HIGHER priority than Promise microtasks:\n\u002F\u002F Node only:\n\u002F\u002F process.nextTick(() => console.log(\"nextTick\"));\n\u002F\u002F Promise.resolve().then(() => console.log(\"promise\"));\n\u002F\u002F console.log(\"sync\");\n\u002F\u002F Output: sync, nextTick, promise (nextTick drains before Promise microtasks)\n",[30,446,447,452,457,461,481,495,527,532,559,572,577,582,587,592,597,601,606,611,616,621,626,631,639,643,648,653,658,663,668,673],{"__ignoreMap":28},[33,448,449],{"class":35,"line":36},[33,450,451],{"class":39},"\u002F\u002F ── The microtask queue is FULLY drained before the next macrotask ──\n",[33,453,454],{"class":35,"line":43},[33,455,456],{"class":39},"\u002F\u002F New microtasks added during the drain ALSO run in the same drain (no limit).\n",[33,458,459],{"class":35,"line":49},[33,460,229],{"emptyLinePlaceholder":228},[33,462,463,465,467,469,472,474,476,478],{"class":35,"line":55},[33,464,304],{"class":290},[33,466,307],{"class":241},[33,468,310],{"class":245},[33,470,471],{"class":241},"().",[33,473,322],{"class":245},[33,475,270],{"class":241},[33,477,274],{"class":273},[33,479,480],{"class":241}," {\n",[33,482,483,486,488,490,493],{"class":35,"line":61},[33,484,485],{"class":241},"    console.",[33,487,246],{"class":245},[33,489,249],{"class":241},[33,491,492],{"class":252},"\"A\"",[33,494,256],{"class":241},[33,496,497,500,502,504,506,508,510,512,514,516,518,521,524],{"class":35,"line":67},[33,498,499],{"class":290},"    Promise",[33,501,307],{"class":241},[33,503,310],{"class":245},[33,505,471],{"class":241},[33,507,322],{"class":245},[33,509,270],{"class":241},[33,511,274],{"class":273},[33,513,277],{"class":241},[33,515,246],{"class":245},[33,517,249],{"class":241},[33,519,520],{"class":252},"\"B\"",[33,522,523],{"class":241},"));  ",[33,525,526],{"class":39},"\u002F\u002F added during drain — runs NOW\n",[33,528,529],{"class":35,"line":73},[33,530,531],{"class":241},"});\n",[33,533,534,536,538,540,542,544,546,548,550,552,554,557],{"class":35,"line":79},[33,535,304],{"class":290},[33,537,307],{"class":241},[33,539,310],{"class":245},[33,541,471],{"class":241},[33,543,322],{"class":245},[33,545,270],{"class":241},[33,547,274],{"class":273},[33,549,277],{"class":241},[33,551,246],{"class":245},[33,553,249],{"class":241},[33,555,556],{"class":252},"\"C\"",[33,558,361],{"class":241},[33,560,561,563,565,567,570],{"class":35,"line":85},[33,562,242],{"class":241},[33,564,246],{"class":245},[33,566,249],{"class":241},[33,568,569],{"class":252},"\"D\"",[33,571,256],{"class":241},[33,573,574],{"class":35,"line":90},[33,575,576],{"class":39},"\u002F\u002F Output: D, A, C, B\n",[33,578,579],{"class":35,"line":96},[33,580,581],{"class":39},"\u002F\u002F D: synchronous\n",[33,583,584],{"class":35,"line":102},[33,585,586],{"class":39},"\u002F\u002F A: first microtask (queued before D finished)\n",[33,588,589],{"class":35,"line":108},[33,590,591],{"class":39},"\u002F\u002F C: second microtask (queued at the same time as A)\n",[33,593,594],{"class":35,"line":114},[33,595,596],{"class":39},"\u002F\u002F B: added during A's execution → runs in the SAME drain (after C, before next macrotask)\n",[33,598,599],{"class":35,"line":120},[33,600,229],{"emptyLinePlaceholder":228},[33,602,603],{"class":35,"line":126},[33,604,605],{"class":39},"\u002F\u002F ── Microtask starvation: infinite microtasks block macrotasks forever ──\n",[33,607,608],{"class":35,"line":132},[33,609,610],{"class":39},"\u002F\u002F (Don't run this — it blocks the event loop)\n",[33,612,613],{"class":35,"line":138},[33,614,615],{"class":39},"\u002F\u002F function infinite() {\n",[33,617,618],{"class":35,"line":144},[33,619,620],{"class":39},"\u002F\u002F     Promise.resolve().then(infinite);\n",[33,622,623],{"class":35,"line":150},[33,624,625],{"class":39},"\u002F\u002F }\n",[33,627,628],{"class":35,"line":156},[33,629,630],{"class":39},"\u002F\u002F infinite();\n",[33,632,633,636],{"class":35,"line":161},[33,634,635],{"class":39},"\u002F\u002F setTimeout(() => console.log(\"never\"), 0);",[33,637,638],{"class":39},"  \u002F\u002F never runs — microtask queue never empties\n",[33,640,641],{"class":35,"line":167},[33,642,229],{"emptyLinePlaceholder":228},[33,644,645],{"class":35,"line":173},[33,646,647],{"class":39},"\u002F\u002F ── Node.js: process.nextTick vs Promise microtask ──\n",[33,649,650],{"class":35,"line":179},[33,651,652],{"class":39},"\u002F\u002F process.nextTick has HIGHER priority than Promise microtasks:\n",[33,654,655],{"class":35,"line":184},[33,656,657],{"class":39},"\u002F\u002F Node only:\n",[33,659,660],{"class":35,"line":190},[33,661,662],{"class":39},"\u002F\u002F process.nextTick(() => console.log(\"nextTick\"));\n",[33,664,665],{"class":35,"line":196},[33,666,667],{"class":39},"\u002F\u002F Promise.resolve().then(() => console.log(\"promise\"));\n",[33,669,670],{"class":35,"line":202},[33,671,672],{"class":39},"\u002F\u002F console.log(\"sync\");\n",[33,674,675],{"class":35,"line":208},[33,676,677],{"class":39},"\u002F\u002F Output: sync, nextTick, promise (nextTick drains before Promise microtasks)\n",[15,679,681],{"id":680},"callbacks-and-the-pyramid-of-doom","Callbacks and the Pyramid of Doom",[20,683,684],{"language":22},[24,685,687],{"className":26,"code":686,"language":22,"meta":28,"style":28},"\u002F\u002F ── Callbacks: the original async pattern (pre-Promises) ──\n\u002F\u002F Node.js error-first callback convention:\nconst fs = require(\"fs\");\nfs.readFile(\"config.json\", \"utf8\", (err, data) => {\n    if (err) {\n        console.error(\"error:\", err);\n        return;\n    }\n    const config = JSON.parse(data);\n    \u002F\u002F Nested callback — \"pyramid of doom\" \u002F \"callback hell\":\n    fs.readFile(config.templatePath, \"utf8\", (err, template) => {\n        if (err) { console.error(err); return; }\n        const rendered = template.replace(\"{{name}}\", config.name);\n        fs.writeFile(config.outputPath, rendered, (err) => {\n            if (err) { console.error(err); return; }\n            console.log(\"done\");\n        });\n    });\n});\n\n\u002F\u002F ── Fix: named functions (flatten the pyramid) ──\nfunction loadConfig(cb) {\n    fs.readFile(\"config.json\", \"utf8\", (err, data) => {\n        if (err) return cb(err);\n        cb(null, JSON.parse(data));\n    });\n}\n\nfunction loadTemplate(config, cb) {\n    fs.readFile(config.templatePath, \"utf8\", (err, template) => {\n        if (err) return cb(err);\n        cb(null, config, template);\n    });\n}\n\nfunction writeOutput(config, template, cb) {\n    const rendered = template.replace(\"{{name}}\", config.name);\n    fs.writeFile(config.outputPath, rendered, cb);\n}\n\n\u002F\u002F Flat chain (no nesting):\nloadConfig((err, config) => {\n    if (err) return console.error(err);\n    loadTemplate(config, (err, template) => {\n        if (err) return console.error(err);\n        writeOutput(config, template, (err) => {\n            if (err) return console.error(err);\n            console.log(\"done\");\n        });\n    });\n});\n",[30,688,689,694,699,720,758,766,782,790,795,816,821,848,867,891,910,925,939,944,949,953,957,962,978,1006,1021,1043,1047,1052,1056,1074,1098,1110,1121,1125,1129,1133,1154,1172,1181,1185,1189,1194,1214,1228,1248,1262,1278,1292,1304,1308,1312],{"__ignoreMap":28},[33,690,691],{"class":35,"line":36},[33,692,693],{"class":39},"\u002F\u002F ── Callbacks: the original async pattern (pre-Promises) ──\n",[33,695,696],{"class":35,"line":43},[33,697,698],{"class":39},"\u002F\u002F Node.js error-first callback convention:\n",[33,700,701,704,707,710,713,715,718],{"class":35,"line":49},[33,702,703],{"class":273},"const",[33,705,706],{"class":290}," fs",[33,708,709],{"class":273}," =",[33,711,712],{"class":245}," require",[33,714,249],{"class":241},[33,716,717],{"class":252},"\"fs\"",[33,719,256],{"class":241},[33,721,722,725,728,730,733,736,739,742,746,748,751,754,756],{"class":35,"line":55},[33,723,724],{"class":241},"fs.",[33,726,727],{"class":245},"readFile",[33,729,249],{"class":241},[33,731,732],{"class":252},"\"config.json\"",[33,734,735],{"class":241},", ",[33,737,738],{"class":252},"\"utf8\"",[33,740,741],{"class":241},", (",[33,743,745],{"class":744},"sCrzJ","err",[33,747,735],{"class":241},[33,749,750],{"class":744},"data",[33,752,753],{"class":241},") ",[33,755,274],{"class":273},[33,757,480],{"class":241},[33,759,760,763],{"class":35,"line":61},[33,761,762],{"class":273},"    if",[33,764,765],{"class":241}," (err) {\n",[33,767,768,771,774,776,779],{"class":35,"line":67},[33,769,770],{"class":241},"        console.",[33,772,773],{"class":245},"error",[33,775,249],{"class":241},[33,777,778],{"class":252},"\"error:\"",[33,780,781],{"class":241},", err);\n",[33,783,784,787],{"class":35,"line":73},[33,785,786],{"class":273},"        return",[33,788,789],{"class":241},";\n",[33,791,792],{"class":35,"line":79},[33,793,794],{"class":241},"    }\n",[33,796,797,800,803,805,808,810,813],{"class":35,"line":85},[33,798,799],{"class":273},"    const",[33,801,802],{"class":290}," config",[33,804,709],{"class":273},[33,806,807],{"class":290}," JSON",[33,809,307],{"class":241},[33,811,812],{"class":245},"parse",[33,814,815],{"class":241},"(data);\n",[33,817,818],{"class":35,"line":90},[33,819,820],{"class":39},"    \u002F\u002F Nested callback — \"pyramid of doom\" \u002F \"callback hell\":\n",[33,822,823,826,828,831,833,835,837,839,842,844,846],{"class":35,"line":96},[33,824,825],{"class":241},"    fs.",[33,827,727],{"class":245},[33,829,830],{"class":241},"(config.templatePath, ",[33,832,738],{"class":252},[33,834,741],{"class":241},[33,836,745],{"class":744},[33,838,735],{"class":241},[33,840,841],{"class":744},"template",[33,843,753],{"class":241},[33,845,274],{"class":273},[33,847,480],{"class":241},[33,849,850,853,856,858,861,864],{"class":35,"line":102},[33,851,852],{"class":273},"        if",[33,854,855],{"class":241}," (err) { console.",[33,857,773],{"class":245},[33,859,860],{"class":241},"(err); ",[33,862,863],{"class":273},"return",[33,865,866],{"class":241},"; }\n",[33,868,869,872,875,877,880,883,885,888],{"class":35,"line":108},[33,870,871],{"class":273},"        const",[33,873,874],{"class":290}," rendered",[33,876,709],{"class":273},[33,878,879],{"class":241}," template.",[33,881,882],{"class":245},"replace",[33,884,249],{"class":241},[33,886,887],{"class":252},"\"{{name}}\"",[33,889,890],{"class":241},", config.name);\n",[33,892,893,896,899,902,904,906,908],{"class":35,"line":114},[33,894,895],{"class":241},"        fs.",[33,897,898],{"class":245},"writeFile",[33,900,901],{"class":241},"(config.outputPath, rendered, (",[33,903,745],{"class":744},[33,905,753],{"class":241},[33,907,274],{"class":273},[33,909,480],{"class":241},[33,911,912,915,917,919,921,923],{"class":35,"line":120},[33,913,914],{"class":273},"            if",[33,916,855],{"class":241},[33,918,773],{"class":245},[33,920,860],{"class":241},[33,922,863],{"class":273},[33,924,866],{"class":241},[33,926,927,930,932,934,937],{"class":35,"line":126},[33,928,929],{"class":241},"            console.",[33,931,246],{"class":245},[33,933,249],{"class":241},[33,935,936],{"class":252},"\"done\"",[33,938,256],{"class":241},[33,940,941],{"class":35,"line":132},[33,942,943],{"class":241},"        });\n",[33,945,946],{"class":35,"line":138},[33,947,948],{"class":241},"    });\n",[33,950,951],{"class":35,"line":144},[33,952,531],{"class":241},[33,954,955],{"class":35,"line":150},[33,956,229],{"emptyLinePlaceholder":228},[33,958,959],{"class":35,"line":156},[33,960,961],{"class":39},"\u002F\u002F ── Fix: named functions (flatten the pyramid) ──\n",[33,963,964,967,970,972,975],{"class":35,"line":161},[33,965,966],{"class":273},"function",[33,968,969],{"class":245}," loadConfig",[33,971,249],{"class":241},[33,973,974],{"class":744},"cb",[33,976,977],{"class":241},") {\n",[33,979,980,982,984,986,988,990,992,994,996,998,1000,1002,1004],{"class":35,"line":167},[33,981,825],{"class":241},[33,983,727],{"class":245},[33,985,249],{"class":241},[33,987,732],{"class":252},[33,989,735],{"class":241},[33,991,738],{"class":252},[33,993,741],{"class":241},[33,995,745],{"class":744},[33,997,735],{"class":241},[33,999,750],{"class":744},[33,1001,753],{"class":241},[33,1003,274],{"class":273},[33,1005,480],{"class":241},[33,1007,1008,1010,1013,1015,1018],{"class":35,"line":173},[33,1009,852],{"class":273},[33,1011,1012],{"class":241}," (err) ",[33,1014,863],{"class":273},[33,1016,1017],{"class":245}," cb",[33,1019,1020],{"class":241},"(err);\n",[33,1022,1023,1026,1028,1031,1033,1036,1038,1040],{"class":35,"line":179},[33,1024,1025],{"class":245},"        cb",[33,1027,249],{"class":241},[33,1029,1030],{"class":290},"null",[33,1032,735],{"class":241},[33,1034,1035],{"class":290},"JSON",[33,1037,307],{"class":241},[33,1039,812],{"class":245},[33,1041,1042],{"class":241},"(data));\n",[33,1044,1045],{"class":35,"line":184},[33,1046,948],{"class":241},[33,1048,1049],{"class":35,"line":190},[33,1050,1051],{"class":241},"}\n",[33,1053,1054],{"class":35,"line":196},[33,1055,229],{"emptyLinePlaceholder":228},[33,1057,1058,1060,1063,1065,1068,1070,1072],{"class":35,"line":202},[33,1059,966],{"class":273},[33,1061,1062],{"class":245}," loadTemplate",[33,1064,249],{"class":241},[33,1066,1067],{"class":744},"config",[33,1069,735],{"class":241},[33,1071,974],{"class":744},[33,1073,977],{"class":241},[33,1075,1076,1078,1080,1082,1084,1086,1088,1090,1092,1094,1096],{"class":35,"line":208},[33,1077,825],{"class":241},[33,1079,727],{"class":245},[33,1081,830],{"class":241},[33,1083,738],{"class":252},[33,1085,741],{"class":241},[33,1087,745],{"class":744},[33,1089,735],{"class":241},[33,1091,841],{"class":744},[33,1093,753],{"class":241},[33,1095,274],{"class":273},[33,1097,480],{"class":241},[33,1099,1100,1102,1104,1106,1108],{"class":35,"line":213},[33,1101,852],{"class":273},[33,1103,1012],{"class":241},[33,1105,863],{"class":273},[33,1107,1017],{"class":245},[33,1109,1020],{"class":241},[33,1111,1112,1114,1116,1118],{"class":35,"line":219},[33,1113,1025],{"class":245},[33,1115,249],{"class":241},[33,1117,1030],{"class":290},[33,1119,1120],{"class":241},", config, template);\n",[33,1122,1123],{"class":35,"line":225},[33,1124,948],{"class":241},[33,1126,1127],{"class":35,"line":232},[33,1128,1051],{"class":241},[33,1130,1131],{"class":35,"line":238},[33,1132,229],{"emptyLinePlaceholder":228},[33,1134,1135,1137,1140,1142,1144,1146,1148,1150,1152],{"class":35,"line":259},[33,1136,966],{"class":273},[33,1138,1139],{"class":245}," writeOutput",[33,1141,249],{"class":241},[33,1143,1067],{"class":744},[33,1145,735],{"class":241},[33,1147,841],{"class":744},[33,1149,735],{"class":241},[33,1151,974],{"class":744},[33,1153,977],{"class":241},[33,1155,1156,1158,1160,1162,1164,1166,1168,1170],{"class":35,"line":264},[33,1157,799],{"class":273},[33,1159,874],{"class":290},[33,1161,709],{"class":273},[33,1163,879],{"class":241},[33,1165,882],{"class":245},[33,1167,249],{"class":241},[33,1169,887],{"class":252},[33,1171,890],{"class":241},[33,1173,1174,1176,1178],{"class":35,"line":296},[33,1175,825],{"class":241},[33,1177,898],{"class":245},[33,1179,1180],{"class":241},"(config.outputPath, rendered, cb);\n",[33,1182,1183],{"class":35,"line":301},[33,1184,1051],{"class":241},[33,1186,1187],{"class":35,"line":316},[33,1188,229],{"emptyLinePlaceholder":228},[33,1190,1191],{"class":35,"line":341},[33,1192,1193],{"class":39},"\u002F\u002F Flat chain (no nesting):\n",[33,1195,1196,1199,1202,1204,1206,1208,1210,1212],{"class":35,"line":364},[33,1197,1198],{"class":245},"loadConfig",[33,1200,1201],{"class":241},"((",[33,1203,745],{"class":744},[33,1205,735],{"class":241},[33,1207,1067],{"class":744},[33,1209,753],{"class":241},[33,1211,274],{"class":273},[33,1213,480],{"class":241},[33,1215,1216,1218,1220,1222,1224,1226],{"class":35,"line":369},[33,1217,762],{"class":273},[33,1219,1012],{"class":241},[33,1221,863],{"class":273},[33,1223,277],{"class":241},[33,1225,773],{"class":245},[33,1227,1020],{"class":241},[33,1229,1230,1233,1236,1238,1240,1242,1244,1246],{"class":35,"line":390},[33,1231,1232],{"class":245},"    loadTemplate",[33,1234,1235],{"class":241},"(config, (",[33,1237,745],{"class":744},[33,1239,735],{"class":241},[33,1241,841],{"class":744},[33,1243,753],{"class":241},[33,1245,274],{"class":273},[33,1247,480],{"class":241},[33,1249,1250,1252,1254,1256,1258,1260],{"class":35,"line":395},[33,1251,852],{"class":273},[33,1253,1012],{"class":241},[33,1255,863],{"class":273},[33,1257,277],{"class":241},[33,1259,773],{"class":245},[33,1261,1020],{"class":241},[33,1263,1264,1267,1270,1272,1274,1276],{"class":35,"line":409},[33,1265,1266],{"class":245},"        writeOutput",[33,1268,1269],{"class":241},"(config, template, (",[33,1271,745],{"class":744},[33,1273,753],{"class":241},[33,1275,274],{"class":273},[33,1277,480],{"class":241},[33,1279,1280,1282,1284,1286,1288,1290],{"class":35,"line":414},[33,1281,914],{"class":273},[33,1283,1012],{"class":241},[33,1285,863],{"class":273},[33,1287,277],{"class":241},[33,1289,773],{"class":245},[33,1291,1020],{"class":241},[33,1293,1294,1296,1298,1300,1302],{"class":35,"line":420},[33,1295,929],{"class":241},[33,1297,246],{"class":245},[33,1299,249],{"class":241},[33,1301,936],{"class":252},[33,1303,256],{"class":241},[33,1305,1306],{"class":35,"line":426},[33,1307,943],{"class":241},[33,1309,1310],{"class":35,"line":432},[33,1311,948],{"class":241},[33,1313,1315],{"class":35,"line":1314},51,[33,1316,531],{"class":241},[15,1318,1320,1321],{"id":1319},"production-pattern-concurrency-with-queuemicrotask","Production Pattern: Concurrency with ",[30,1322,372],{},[20,1324,1325],{"language":22},[24,1326,1328],{"className":26,"code":1327,"language":22,"meta":28,"style":28},"\u002F\u002F ── queueMicrotask: schedule a microtask without a Promise ──\n\u002F\u002F Lower latency than setTimeout(fn, 0) — runs before the next macrotask.\n\n\u002F\u002F Use case: batch synchronous work into microtasks (yield to the event loop faster)\nfunction batchProcess(items, processor) {\n    let i = 0;\n    function processChunk() {\n        const chunk = items.slice(i, i + 1000);\n        for (const item of chunk) processor(item);\n        i += 1000;\n        if (i \u003C items.length) {\n            queueMicrotask(processChunk);  \u002F\u002F schedule next chunk as a microtask\n        }\n    }\n    processChunk();\n}\n\n\u002F\u002F ── Use case: schedule after current synchronous work, before render ──\nqueueMicrotask(() => {\n    \u002F\u002F Runs after current sync code, before the browser paints\n    \u002F\u002F Useful for updating DOM without causing a flash\n    element.textContent = \"updated\";\n});\n\n\u002F\u002F ── Comparison: queueMicrotask vs setTimeout ──\nqueueMicrotask(() => console.log(\"microtask\"));  \u002F\u002F runs after current task, before next macrotask\nsetTimeout(() => console.log(\"macrotask\"), 0);   \u002F\u002F runs after next macrotask\nconsole.log(\"sync\");\n\u002F\u002F Output: sync, microtask, macrotask\n\u002F\u002F Microtask is higher priority (runs first, before setTimeout)\n",[30,1329,1330,1335,1340,1344,1349,1368,1384,1395,1421,1445,1457,1474,1485,1490,1494,1502,1506,1510,1515,1525,1530,1535,1547,1551,1555,1560,1582,1609,1622,1627],{"__ignoreMap":28},[33,1331,1332],{"class":35,"line":36},[33,1333,1334],{"class":39},"\u002F\u002F ── queueMicrotask: schedule a microtask without a Promise ──\n",[33,1336,1337],{"class":35,"line":43},[33,1338,1339],{"class":39},"\u002F\u002F Lower latency than setTimeout(fn, 0) — runs before the next macrotask.\n",[33,1341,1342],{"class":35,"line":49},[33,1343,229],{"emptyLinePlaceholder":228},[33,1345,1346],{"class":35,"line":55},[33,1347,1348],{"class":39},"\u002F\u002F Use case: batch synchronous work into microtasks (yield to the event loop faster)\n",[33,1350,1351,1353,1356,1358,1361,1363,1366],{"class":35,"line":61},[33,1352,966],{"class":273},[33,1354,1355],{"class":245}," batchProcess",[33,1357,249],{"class":241},[33,1359,1360],{"class":744},"items",[33,1362,735],{"class":241},[33,1364,1365],{"class":744},"processor",[33,1367,977],{"class":241},[33,1369,1370,1373,1376,1379,1382],{"class":35,"line":67},[33,1371,1372],{"class":273},"    let",[33,1374,1375],{"class":241}," i ",[33,1377,1378],{"class":273},"=",[33,1380,1381],{"class":290}," 0",[33,1383,789],{"class":241},[33,1385,1386,1389,1392],{"class":35,"line":73},[33,1387,1388],{"class":273},"    function",[33,1390,1391],{"class":245}," processChunk",[33,1393,1394],{"class":241},"() {\n",[33,1396,1397,1399,1402,1404,1407,1410,1413,1416,1419],{"class":35,"line":79},[33,1398,871],{"class":273},[33,1400,1401],{"class":290}," chunk",[33,1403,709],{"class":273},[33,1405,1406],{"class":241}," items.",[33,1408,1409],{"class":245},"slice",[33,1411,1412],{"class":241},"(i, i ",[33,1414,1415],{"class":273},"+",[33,1417,1418],{"class":290}," 1000",[33,1420,256],{"class":241},[33,1422,1423,1426,1429,1431,1434,1437,1440,1442],{"class":35,"line":85},[33,1424,1425],{"class":273},"        for",[33,1427,1428],{"class":241}," (",[33,1430,703],{"class":273},[33,1432,1433],{"class":290}," item",[33,1435,1436],{"class":273}," of",[33,1438,1439],{"class":241}," chunk) ",[33,1441,1365],{"class":245},[33,1443,1444],{"class":241},"(item);\n",[33,1446,1447,1450,1453,1455],{"class":35,"line":90},[33,1448,1449],{"class":241},"        i ",[33,1451,1452],{"class":273},"+=",[33,1454,1418],{"class":290},[33,1456,789],{"class":241},[33,1458,1459,1461,1464,1467,1469,1472],{"class":35,"line":96},[33,1460,852],{"class":273},[33,1462,1463],{"class":241}," (i ",[33,1465,1466],{"class":273},"\u003C",[33,1468,1406],{"class":241},[33,1470,1471],{"class":290},"length",[33,1473,977],{"class":241},[33,1475,1476,1479,1482],{"class":35,"line":102},[33,1477,1478],{"class":245},"            queueMicrotask",[33,1480,1481],{"class":241},"(processChunk);  ",[33,1483,1484],{"class":39},"\u002F\u002F schedule next chunk as a microtask\n",[33,1486,1487],{"class":35,"line":108},[33,1488,1489],{"class":241},"        }\n",[33,1491,1492],{"class":35,"line":114},[33,1493,794],{"class":241},[33,1495,1496,1499],{"class":35,"line":120},[33,1497,1498],{"class":245},"    processChunk",[33,1500,1501],{"class":241},"();\n",[33,1503,1504],{"class":35,"line":126},[33,1505,1051],{"class":241},[33,1507,1508],{"class":35,"line":132},[33,1509,229],{"emptyLinePlaceholder":228},[33,1511,1512],{"class":35,"line":138},[33,1513,1514],{"class":39},"\u002F\u002F ── Use case: schedule after current synchronous work, before render ──\n",[33,1516,1517,1519,1521,1523],{"class":35,"line":144},[33,1518,372],{"class":245},[33,1520,270],{"class":241},[33,1522,274],{"class":273},[33,1524,480],{"class":241},[33,1526,1527],{"class":35,"line":150},[33,1528,1529],{"class":39},"    \u002F\u002F Runs after current sync code, before the browser paints\n",[33,1531,1532],{"class":35,"line":156},[33,1533,1534],{"class":39},"    \u002F\u002F Useful for updating DOM without causing a flash\n",[33,1536,1537,1540,1542,1545],{"class":35,"line":161},[33,1538,1539],{"class":241},"    element.textContent ",[33,1541,1378],{"class":273},[33,1543,1544],{"class":252}," \"updated\"",[33,1546,789],{"class":241},[33,1548,1549],{"class":35,"line":167},[33,1550,531],{"class":241},[33,1552,1553],{"class":35,"line":173},[33,1554,229],{"emptyLinePlaceholder":228},[33,1556,1557],{"class":35,"line":179},[33,1558,1559],{"class":39},"\u002F\u002F ── Comparison: queueMicrotask vs setTimeout ──\n",[33,1561,1562,1564,1566,1568,1570,1572,1574,1577,1579],{"class":35,"line":184},[33,1563,372],{"class":245},[33,1565,270],{"class":241},[33,1567,274],{"class":273},[33,1569,277],{"class":241},[33,1571,246],{"class":245},[33,1573,249],{"class":241},[33,1575,1576],{"class":252},"\"microtask\"",[33,1578,523],{"class":241},[33,1580,1581],{"class":39},"\u002F\u002F runs after current task, before next macrotask\n",[33,1583,1584,1586,1588,1590,1592,1594,1596,1599,1601,1603,1606],{"class":35,"line":190},[33,1585,267],{"class":245},[33,1587,270],{"class":241},[33,1589,274],{"class":273},[33,1591,277],{"class":241},[33,1593,246],{"class":245},[33,1595,249],{"class":241},[33,1597,1598],{"class":252},"\"macrotask\"",[33,1600,287],{"class":241},[33,1602,291],{"class":290},[33,1604,1605],{"class":241},");   ",[33,1607,1608],{"class":39},"\u002F\u002F runs after next macrotask\n",[33,1610,1611,1613,1615,1617,1620],{"class":35,"line":196},[33,1612,242],{"class":241},[33,1614,246],{"class":245},[33,1616,249],{"class":241},[33,1618,1619],{"class":252},"\"sync\"",[33,1621,256],{"class":241},[33,1623,1624],{"class":35,"line":202},[33,1625,1626],{"class":39},"\u002F\u002F Output: sync, microtask, macrotask\n",[33,1628,1629],{"class":35,"line":208},[33,1630,1631],{"class":39},"\u002F\u002F Microtask is higher priority (runs first, before setTimeout)\n",[15,1633,1635],{"id":1634},"anti-pattern-blocking-the-event-loop","Anti-Pattern: Blocking the Event Loop",[20,1637,1638],{"language":22},[24,1639,1641],{"className":26,"code":1640,"language":22,"meta":28,"style":28},"\u002F\u002F ❌ NAIVE — synchronous CPU-bound work blocks the event loop\nfunction heavyCompute(n) {\n    let sum = 0;\n    for (let i = 0; i \u003C n; i++) sum += Math.sqrt(i);\n    return sum;\n}\n\u002F\u002F heavyCompute(1_000_000_000);  \u002F\u002F blocks the event loop for seconds — no UI updates, no timers\n\n\u002F\u002F ✅ CORRECT — chunk the work with setTimeout to yield to the event loop\nasync function chunkedCompute(n, chunkSize = 10_000) {\n    let sum = 0;\n    let i = 0;\n    return new Promise(resolve => {\n        function chunk() {\n            const end = Math.min(i + chunkSize, n);\n            for (; i \u003C end; i++) sum += Math.sqrt(i);\n            if (i \u003C n) {\n                setTimeout(chunk, 0);  \u002F\u002F yield — lets timers\u002FUI\u002FIO run between chunks\n            } else {\n                resolve(sum);\n            }\n        }\n        chunk();\n    });\n}\n\u002F\u002F chunkedCompute(1_000_000_000).then(console.log);  \u002F\u002F UI stays responsive\n\n\u002F\u002F ✅ BEST — use a Web Worker (true parallelism, doesn't block the main thread)\n\u002F\u002F main.js:\n\u002F\u002F const worker = new Worker(\".\u002Fcompute-worker.js\");\n\u002F\u002F worker.postMessage(1_000_000_000);\n\u002F\u002F worker.onmessage = (e) => console.log(\"result:\", e.data);\n\n\u002F\u002F compute-worker.js:\n\u002F\u002F self.onmessage = (e) => {\n\u002F\u002F     let sum = 0;\n\u002F\u002F     for (let i = 0; i \u003C e.data; i++) sum += Math.sqrt(i);\n\u002F\u002F     self.postMessage(sum);\n\u002F\u002F };\n",[30,1642,1643,1648,1662,1675,1716,1724,1728,1736,1740,1745,1772,1784,1796,1815,1824,1847,1872,1883,1899,1909,1917,1922,1926,1933,1937,1941,1949,1953,1958,1963,1968,1973,1978,1982,1987,1992,1997,2002,2007],{"__ignoreMap":28},[33,1644,1645],{"class":35,"line":36},[33,1646,1647],{"class":39},"\u002F\u002F ❌ NAIVE — synchronous CPU-bound work blocks the event loop\n",[33,1649,1650,1652,1655,1657,1660],{"class":35,"line":43},[33,1651,966],{"class":273},[33,1653,1654],{"class":245}," heavyCompute",[33,1656,249],{"class":241},[33,1658,1659],{"class":744},"n",[33,1661,977],{"class":241},[33,1663,1664,1666,1669,1671,1673],{"class":35,"line":49},[33,1665,1372],{"class":273},[33,1667,1668],{"class":241}," sum ",[33,1670,1378],{"class":273},[33,1672,1381],{"class":290},[33,1674,789],{"class":241},[33,1676,1677,1680,1682,1685,1687,1689,1691,1694,1696,1699,1702,1705,1707,1710,1713],{"class":35,"line":55},[33,1678,1679],{"class":273},"    for",[33,1681,1428],{"class":241},[33,1683,1684],{"class":273},"let",[33,1686,1375],{"class":241},[33,1688,1378],{"class":273},[33,1690,1381],{"class":290},[33,1692,1693],{"class":241},"; i ",[33,1695,1466],{"class":273},[33,1697,1698],{"class":241}," n; i",[33,1700,1701],{"class":273},"++",[33,1703,1704],{"class":241},") sum ",[33,1706,1452],{"class":273},[33,1708,1709],{"class":241}," Math.",[33,1711,1712],{"class":245},"sqrt",[33,1714,1715],{"class":241},"(i);\n",[33,1717,1718,1721],{"class":35,"line":61},[33,1719,1720],{"class":273},"    return",[33,1722,1723],{"class":241}," sum;\n",[33,1725,1726],{"class":35,"line":67},[33,1727,1051],{"class":241},[33,1729,1730,1733],{"class":35,"line":73},[33,1731,1732],{"class":39},"\u002F\u002F heavyCompute(1_000_000_000);",[33,1734,1735],{"class":39},"  \u002F\u002F blocks the event loop for seconds — no UI updates, no timers\n",[33,1737,1738],{"class":35,"line":79},[33,1739,229],{"emptyLinePlaceholder":228},[33,1741,1742],{"class":35,"line":85},[33,1743,1744],{"class":39},"\u002F\u002F ✅ CORRECT — chunk the work with setTimeout to yield to the event loop\n",[33,1746,1747,1750,1753,1756,1758,1760,1762,1765,1767,1770],{"class":35,"line":90},[33,1748,1749],{"class":273},"async",[33,1751,1752],{"class":273}," function",[33,1754,1755],{"class":245}," chunkedCompute",[33,1757,249],{"class":241},[33,1759,1659],{"class":744},[33,1761,735],{"class":241},[33,1763,1764],{"class":744},"chunkSize",[33,1766,709],{"class":273},[33,1768,1769],{"class":290}," 10_000",[33,1771,977],{"class":241},[33,1773,1774,1776,1778,1780,1782],{"class":35,"line":96},[33,1775,1372],{"class":273},[33,1777,1668],{"class":241},[33,1779,1378],{"class":273},[33,1781,1381],{"class":290},[33,1783,789],{"class":241},[33,1785,1786,1788,1790,1792,1794],{"class":35,"line":102},[33,1787,1372],{"class":273},[33,1789,1375],{"class":241},[33,1791,1378],{"class":273},[33,1793,1381],{"class":290},[33,1795,789],{"class":241},[33,1797,1798,1800,1803,1806,1808,1810,1813],{"class":35,"line":108},[33,1799,1720],{"class":273},[33,1801,1802],{"class":273}," new",[33,1804,1805],{"class":290}," Promise",[33,1807,249],{"class":241},[33,1809,310],{"class":744},[33,1811,1812],{"class":273}," =>",[33,1814,480],{"class":241},[33,1816,1817,1820,1822],{"class":35,"line":114},[33,1818,1819],{"class":273},"        function",[33,1821,1401],{"class":245},[33,1823,1394],{"class":241},[33,1825,1826,1829,1832,1834,1836,1839,1842,1844],{"class":35,"line":120},[33,1827,1828],{"class":273},"            const",[33,1830,1831],{"class":290}," end",[33,1833,709],{"class":273},[33,1835,1709],{"class":241},[33,1837,1838],{"class":245},"min",[33,1840,1841],{"class":241},"(i ",[33,1843,1415],{"class":273},[33,1845,1846],{"class":241}," chunkSize, n);\n",[33,1848,1849,1852,1855,1857,1860,1862,1864,1866,1868,1870],{"class":35,"line":126},[33,1850,1851],{"class":273},"            for",[33,1853,1854],{"class":241}," (; i ",[33,1856,1466],{"class":273},[33,1858,1859],{"class":241}," end; i",[33,1861,1701],{"class":273},[33,1863,1704],{"class":241},[33,1865,1452],{"class":273},[33,1867,1709],{"class":241},[33,1869,1712],{"class":245},[33,1871,1715],{"class":241},[33,1873,1874,1876,1878,1880],{"class":35,"line":132},[33,1875,914],{"class":273},[33,1877,1463],{"class":241},[33,1879,1466],{"class":273},[33,1881,1882],{"class":241}," n) {\n",[33,1884,1885,1888,1891,1893,1896],{"class":35,"line":138},[33,1886,1887],{"class":245},"                setTimeout",[33,1889,1890],{"class":241},"(chunk, ",[33,1892,291],{"class":290},[33,1894,1895],{"class":241},");  ",[33,1897,1898],{"class":39},"\u002F\u002F yield — lets timers\u002FUI\u002FIO run between chunks\n",[33,1900,1901,1904,1907],{"class":35,"line":144},[33,1902,1903],{"class":241},"            } ",[33,1905,1906],{"class":273},"else",[33,1908,480],{"class":241},[33,1910,1911,1914],{"class":35,"line":150},[33,1912,1913],{"class":245},"                resolve",[33,1915,1916],{"class":241},"(sum);\n",[33,1918,1919],{"class":35,"line":156},[33,1920,1921],{"class":241},"            }\n",[33,1923,1924],{"class":35,"line":161},[33,1925,1489],{"class":241},[33,1927,1928,1931],{"class":35,"line":167},[33,1929,1930],{"class":245},"        chunk",[33,1932,1501],{"class":241},[33,1934,1935],{"class":35,"line":173},[33,1936,948],{"class":241},[33,1938,1939],{"class":35,"line":179},[33,1940,1051],{"class":241},[33,1942,1943,1946],{"class":35,"line":184},[33,1944,1945],{"class":39},"\u002F\u002F chunkedCompute(1_000_000_000).then(console.log);",[33,1947,1948],{"class":39},"  \u002F\u002F UI stays responsive\n",[33,1950,1951],{"class":35,"line":190},[33,1952,229],{"emptyLinePlaceholder":228},[33,1954,1955],{"class":35,"line":196},[33,1956,1957],{"class":39},"\u002F\u002F ✅ BEST — use a Web Worker (true parallelism, doesn't block the main thread)\n",[33,1959,1960],{"class":35,"line":202},[33,1961,1962],{"class":39},"\u002F\u002F main.js:\n",[33,1964,1965],{"class":35,"line":208},[33,1966,1967],{"class":39},"\u002F\u002F const worker = new Worker(\".\u002Fcompute-worker.js\");\n",[33,1969,1970],{"class":35,"line":213},[33,1971,1972],{"class":39},"\u002F\u002F worker.postMessage(1_000_000_000);\n",[33,1974,1975],{"class":35,"line":219},[33,1976,1977],{"class":39},"\u002F\u002F worker.onmessage = (e) => console.log(\"result:\", e.data);\n",[33,1979,1980],{"class":35,"line":225},[33,1981,229],{"emptyLinePlaceholder":228},[33,1983,1984],{"class":35,"line":232},[33,1985,1986],{"class":39},"\u002F\u002F compute-worker.js:\n",[33,1988,1989],{"class":35,"line":238},[33,1990,1991],{"class":39},"\u002F\u002F self.onmessage = (e) => {\n",[33,1993,1994],{"class":35,"line":259},[33,1995,1996],{"class":39},"\u002F\u002F     let sum = 0;\n",[33,1998,1999],{"class":35,"line":264},[33,2000,2001],{"class":39},"\u002F\u002F     for (let i = 0; i \u003C e.data; i++) sum += Math.sqrt(i);\n",[33,2003,2004],{"class":35,"line":296},[33,2005,2006],{"class":39},"\u002F\u002F     self.postMessage(sum);\n",[33,2008,2009],{"class":35,"line":301},[33,2010,2011],{"class":39},"\u002F\u002F };\n",[15,2013,2015],{"id":2014},"tips-tricks","💡 Tips & Tricks",[20,2017,2018],{"language":22},[24,2019,2021],{"className":26,"code":2020,"language":22,"meta":28,"style":28},"\u002F\u002F ── Promise.resolve().then() as a microtask scheduler ──\nPromise.resolve().then(() => console.log(\"microtask via Promise\"));\n\u002F\u002F Same as queueMicrotask but uses a Promise (slightly more overhead, but more compatible)\n\n\u002F\u002F ── scheduler.yield() (Chrome 129+) — modern way to yield ──\nasync function yieldToEventLoop() {\n    if (typeof scheduler !== \"undefined\" && scheduler.yield) {\n        await scheduler.yield();  \u002F\u002F higher priority than setTimeout (runs sooner)\n    } else {\n        await new Promise(r => setTimeout(r, 0));  \u002F\u002F fallback\n    }\n}\n\n\u002F\u002F ── AbortController for cancellable async operations ──\nconst controller = new AbortController();\nsetTimeout(() => controller.abort(), 5000);  \u002F\u002F abort after 5s\nfetch(\"\u002Fapi\u002Fdata\", { signal: controller.signal })\n    .then(r => r.json())\n    .catch(err => {\n        if (err.name === \"AbortError\") console.log(\"aborted\");\n        else throw err;\n    });\n\n\u002F\u002F ── Measuring event loop latency (Node.js) ──\n\u002F\u002F Node only:\n\u002F\u002F let last = process.hrtime.bigint();\n\u002F\u002F setInterval(() => {\n\u002F\u002F     const now = process.hrtime.bigint();\n\u002F\u002F     const lag = Number(now - last) \u002F 1e6 - 1000;  \u002F\u002F ms over expected\n\u002F\u002F     console.log(\"event loop lag:\", lag, \"ms\");\n\u002F\u002F     last = now;\n\u002F\u002F }, 1000);\n",[30,2022,2023,2028,2055,2060,2064,2069,2080,2104,2121,2130,2158,2162,2166,2170,2175,2191,2216,2229,2250,2265,2290,2301,2305,2309,2314,2318,2323,2328,2333,2341,2346,2351],{"__ignoreMap":28},[33,2024,2025],{"class":35,"line":36},[33,2026,2027],{"class":39},"\u002F\u002F ── Promise.resolve().then() as a microtask scheduler ──\n",[33,2029,2030,2032,2034,2036,2038,2040,2042,2044,2046,2048,2050,2053],{"class":35,"line":43},[33,2031,304],{"class":290},[33,2033,307],{"class":241},[33,2035,310],{"class":245},[33,2037,471],{"class":241},[33,2039,322],{"class":245},[33,2041,270],{"class":241},[33,2043,274],{"class":273},[33,2045,277],{"class":241},[33,2047,246],{"class":245},[33,2049,249],{"class":241},[33,2051,2052],{"class":252},"\"microtask via Promise\"",[33,2054,361],{"class":241},[33,2056,2057],{"class":35,"line":49},[33,2058,2059],{"class":39},"\u002F\u002F Same as queueMicrotask but uses a Promise (slightly more overhead, but more compatible)\n",[33,2061,2062],{"class":35,"line":55},[33,2063,229],{"emptyLinePlaceholder":228},[33,2065,2066],{"class":35,"line":61},[33,2067,2068],{"class":39},"\u002F\u002F ── scheduler.yield() (Chrome 129+) — modern way to yield ──\n",[33,2070,2071,2073,2075,2078],{"class":35,"line":67},[33,2072,1749],{"class":273},[33,2074,1752],{"class":273},[33,2076,2077],{"class":245}," yieldToEventLoop",[33,2079,1394],{"class":241},[33,2081,2082,2084,2086,2089,2092,2095,2098,2101],{"class":35,"line":73},[33,2083,762],{"class":273},[33,2085,1428],{"class":241},[33,2087,2088],{"class":273},"typeof",[33,2090,2091],{"class":241}," scheduler ",[33,2093,2094],{"class":273},"!==",[33,2096,2097],{"class":252}," \"undefined\"",[33,2099,2100],{"class":273}," &&",[33,2102,2103],{"class":241}," scheduler.yield) {\n",[33,2105,2106,2109,2112,2115,2118],{"class":35,"line":79},[33,2107,2108],{"class":273},"        await",[33,2110,2111],{"class":241}," scheduler.",[33,2113,2114],{"class":245},"yield",[33,2116,2117],{"class":241},"();  ",[33,2119,2120],{"class":39},"\u002F\u002F higher priority than setTimeout (runs sooner)\n",[33,2122,2123,2126,2128],{"class":35,"line":85},[33,2124,2125],{"class":241},"    } ",[33,2127,1906],{"class":273},[33,2129,480],{"class":241},[33,2131,2132,2134,2136,2138,2140,2143,2145,2148,2151,2153,2155],{"class":35,"line":90},[33,2133,2108],{"class":273},[33,2135,1802],{"class":273},[33,2137,1805],{"class":290},[33,2139,249],{"class":241},[33,2141,2142],{"class":744},"r",[33,2144,1812],{"class":273},[33,2146,2147],{"class":245}," setTimeout",[33,2149,2150],{"class":241},"(r, ",[33,2152,291],{"class":290},[33,2154,523],{"class":241},[33,2156,2157],{"class":39},"\u002F\u002F fallback\n",[33,2159,2160],{"class":35,"line":96},[33,2161,794],{"class":241},[33,2163,2164],{"class":35,"line":102},[33,2165,1051],{"class":241},[33,2167,2168],{"class":35,"line":108},[33,2169,229],{"emptyLinePlaceholder":228},[33,2171,2172],{"class":35,"line":114},[33,2173,2174],{"class":39},"\u002F\u002F ── AbortController for cancellable async operations ──\n",[33,2176,2177,2179,2182,2184,2186,2189],{"class":35,"line":120},[33,2178,703],{"class":273},[33,2180,2181],{"class":290}," controller",[33,2183,709],{"class":273},[33,2185,1802],{"class":273},[33,2187,2188],{"class":245}," AbortController",[33,2190,1501],{"class":241},[33,2192,2193,2195,2197,2199,2202,2205,2208,2211,2213],{"class":35,"line":126},[33,2194,267],{"class":245},[33,2196,270],{"class":241},[33,2198,274],{"class":273},[33,2200,2201],{"class":241}," controller.",[33,2203,2204],{"class":245},"abort",[33,2206,2207],{"class":241},"(), ",[33,2209,2210],{"class":290},"5000",[33,2212,1895],{"class":241},[33,2214,2215],{"class":39},"\u002F\u002F abort after 5s\n",[33,2217,2218,2221,2223,2226],{"class":35,"line":132},[33,2219,2220],{"class":245},"fetch",[33,2222,249],{"class":241},[33,2224,2225],{"class":252},"\"\u002Fapi\u002Fdata\"",[33,2227,2228],{"class":241},", { signal: controller.signal })\n",[33,2230,2231,2233,2235,2237,2239,2241,2244,2247],{"class":35,"line":138},[33,2232,319],{"class":241},[33,2234,322],{"class":245},[33,2236,249],{"class":241},[33,2238,2142],{"class":744},[33,2240,1812],{"class":273},[33,2242,2243],{"class":241}," r.",[33,2245,2246],{"class":245},"json",[33,2248,2249],{"class":241},"())\n",[33,2251,2252,2254,2257,2259,2261,2263],{"class":35,"line":144},[33,2253,319],{"class":241},[33,2255,2256],{"class":245},"catch",[33,2258,249],{"class":241},[33,2260,745],{"class":744},[33,2262,1812],{"class":273},[33,2264,480],{"class":241},[33,2266,2267,2269,2272,2275,2278,2281,2283,2285,2288],{"class":35,"line":150},[33,2268,852],{"class":273},[33,2270,2271],{"class":241}," (err.name ",[33,2273,2274],{"class":273},"===",[33,2276,2277],{"class":252}," \"AbortError\"",[33,2279,2280],{"class":241},") console.",[33,2282,246],{"class":245},[33,2284,249],{"class":241},[33,2286,2287],{"class":252},"\"aborted\"",[33,2289,256],{"class":241},[33,2291,2292,2295,2298],{"class":35,"line":156},[33,2293,2294],{"class":273},"        else",[33,2296,2297],{"class":273}," throw",[33,2299,2300],{"class":241}," err;\n",[33,2302,2303],{"class":35,"line":161},[33,2304,948],{"class":241},[33,2306,2307],{"class":35,"line":167},[33,2308,229],{"emptyLinePlaceholder":228},[33,2310,2311],{"class":35,"line":173},[33,2312,2313],{"class":39},"\u002F\u002F ── Measuring event loop latency (Node.js) ──\n",[33,2315,2316],{"class":35,"line":179},[33,2317,657],{"class":39},[33,2319,2320],{"class":35,"line":184},[33,2321,2322],{"class":39},"\u002F\u002F let last = process.hrtime.bigint();\n",[33,2324,2325],{"class":35,"line":190},[33,2326,2327],{"class":39},"\u002F\u002F setInterval(() => {\n",[33,2329,2330],{"class":35,"line":196},[33,2331,2332],{"class":39},"\u002F\u002F     const now = process.hrtime.bigint();\n",[33,2334,2335,2338],{"class":35,"line":202},[33,2336,2337],{"class":39},"\u002F\u002F     const lag = Number(now - last) \u002F 1e6 - 1000;",[33,2339,2340],{"class":39},"  \u002F\u002F ms over expected\n",[33,2342,2343],{"class":35,"line":208},[33,2344,2345],{"class":39},"\u002F\u002F     console.log(\"event loop lag:\", lag, \"ms\");\n",[33,2347,2348],{"class":35,"line":213},[33,2349,2350],{"class":39},"\u002F\u002F     last = now;\n",[33,2352,2353],{"class":35,"line":219},[33,2354,2355],{"class":39},"\u002F\u002F }, 1000);\n",[15,2357,2359],{"id":2358},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[20,2361,2362],{"language":22},[24,2363,2365],{"className":26,"code":2364,"language":22,"meta":28,"style":28},"\u002F\u002F ── setTimeout(fn, 0) doesn't run immediately — it's a macrotask ──\n\u002F\u002F It runs after the current script AND all queued microtasks complete.\nconsole.log(\"A\");\nsetTimeout(() => console.log(\"C\"), 0);\nPromise.resolve().then(() => console.log(\"B\"));\nconsole.log(\"D\");\n\u002F\u002F Output: A, D, B, C (B is microtask — runs before C which is macrotask)\n\n\u002F\u002F ── setInterval drift: timer doesn't fire at exact intervals ──\n\u002F\u002F setInterval fires AFTER the macrotask queue processes it, not at exact intervals.\n\u002F\u002F If the event loop is busy, intervals are delayed.\n\u002F\u002F Use a self-correcting timer:\nlet expected = Date.now();\nfunction accurateInterval(fn, delay) {\n    function tick() {\n        const drift = Date.now() - expected;\n        fn(drift);  \u002F\u002F pass drift so the callback can adjust\n        expected += delay;\n        setTimeout(tick, Math.max(0, delay - drift));  \u002F\u002F correct for drift\n    }\n    setTimeout(tick, delay);\n}\n\n\u002F\u002F ── Microtasks can starve macrotasks (infinite loop) ──\n\u002F\u002F A microtask that adds another microtask never lets macrotasks run.\n\u002F\u002F Don't create infinite microtask chains.\n\n\u002F\u002F ── `await` yields to the event loop (it's a microtask boundary) ──\nasync function f() {\n    console.log(\"A\");\n    await Promise.resolve();  \u002F\u002F yields — microtasks\u002Ftimers can run here\n    console.log(\"B\");\n}\nf();\nconsole.log(\"C\");\n\u002F\u002F Output: A, C, B (await suspends, C runs, then B resumes as a microtask)\n\n\u002F\u002F ── `requestAnimationFrame` runs before paint, not on the event loop tick ──\n\u002F\u002F rAF callbacks run in the render phase (after microtasks, before paint).\n\u002F\u002F They're not macrotasks — they run at the browser's frame rate (~60fps).\n",[30,2366,2367,2372,2377,2389,2411,2437,2449,2454,2458,2463,2468,2473,2478,2495,2514,2523,2545,2556,2566,2592,2596,2604,2608,2612,2617,2622,2627,2631,2636,2647,2659,2675,2687,2691,2698,2710,2715,2719,2724,2729],{"__ignoreMap":28},[33,2368,2369],{"class":35,"line":36},[33,2370,2371],{"class":39},"\u002F\u002F ── setTimeout(fn, 0) doesn't run immediately — it's a macrotask ──\n",[33,2373,2374],{"class":35,"line":43},[33,2375,2376],{"class":39},"\u002F\u002F It runs after the current script AND all queued microtasks complete.\n",[33,2378,2379,2381,2383,2385,2387],{"class":35,"line":49},[33,2380,242],{"class":241},[33,2382,246],{"class":245},[33,2384,249],{"class":241},[33,2386,492],{"class":252},[33,2388,256],{"class":241},[33,2390,2391,2393,2395,2397,2399,2401,2403,2405,2407,2409],{"class":35,"line":55},[33,2392,267],{"class":245},[33,2394,270],{"class":241},[33,2396,274],{"class":273},[33,2398,277],{"class":241},[33,2400,246],{"class":245},[33,2402,249],{"class":241},[33,2404,556],{"class":252},[33,2406,287],{"class":241},[33,2408,291],{"class":290},[33,2410,256],{"class":241},[33,2412,2413,2415,2417,2419,2421,2423,2425,2427,2429,2431,2433,2435],{"class":35,"line":61},[33,2414,304],{"class":290},[33,2416,307],{"class":241},[33,2418,310],{"class":245},[33,2420,471],{"class":241},[33,2422,322],{"class":245},[33,2424,270],{"class":241},[33,2426,274],{"class":273},[33,2428,277],{"class":241},[33,2430,246],{"class":245},[33,2432,249],{"class":241},[33,2434,520],{"class":252},[33,2436,361],{"class":241},[33,2438,2439,2441,2443,2445,2447],{"class":35,"line":67},[33,2440,242],{"class":241},[33,2442,246],{"class":245},[33,2444,249],{"class":241},[33,2446,569],{"class":252},[33,2448,256],{"class":241},[33,2450,2451],{"class":35,"line":73},[33,2452,2453],{"class":39},"\u002F\u002F Output: A, D, B, C (B is microtask — runs before C which is macrotask)\n",[33,2455,2456],{"class":35,"line":79},[33,2457,229],{"emptyLinePlaceholder":228},[33,2459,2460],{"class":35,"line":85},[33,2461,2462],{"class":39},"\u002F\u002F ── setInterval drift: timer doesn't fire at exact intervals ──\n",[33,2464,2465],{"class":35,"line":90},[33,2466,2467],{"class":39},"\u002F\u002F setInterval fires AFTER the macrotask queue processes it, not at exact intervals.\n",[33,2469,2470],{"class":35,"line":96},[33,2471,2472],{"class":39},"\u002F\u002F If the event loop is busy, intervals are delayed.\n",[33,2474,2475],{"class":35,"line":102},[33,2476,2477],{"class":39},"\u002F\u002F Use a self-correcting timer:\n",[33,2479,2480,2482,2485,2487,2490,2493],{"class":35,"line":108},[33,2481,1684],{"class":273},[33,2483,2484],{"class":241}," expected ",[33,2486,1378],{"class":273},[33,2488,2489],{"class":241}," Date.",[33,2491,2492],{"class":245},"now",[33,2494,1501],{"class":241},[33,2496,2497,2499,2502,2504,2507,2509,2512],{"class":35,"line":114},[33,2498,966],{"class":273},[33,2500,2501],{"class":245}," accurateInterval",[33,2503,249],{"class":241},[33,2505,2506],{"class":744},"fn",[33,2508,735],{"class":241},[33,2510,2511],{"class":744},"delay",[33,2513,977],{"class":241},[33,2515,2516,2518,2521],{"class":35,"line":120},[33,2517,1388],{"class":273},[33,2519,2520],{"class":245}," tick",[33,2522,1394],{"class":241},[33,2524,2525,2527,2530,2532,2534,2536,2539,2542],{"class":35,"line":126},[33,2526,871],{"class":273},[33,2528,2529],{"class":290}," drift",[33,2531,709],{"class":273},[33,2533,2489],{"class":241},[33,2535,2492],{"class":245},[33,2537,2538],{"class":241},"() ",[33,2540,2541],{"class":273},"-",[33,2543,2544],{"class":241}," expected;\n",[33,2546,2547,2550,2553],{"class":35,"line":132},[33,2548,2549],{"class":245},"        fn",[33,2551,2552],{"class":241},"(drift);  ",[33,2554,2555],{"class":39},"\u002F\u002F pass drift so the callback can adjust\n",[33,2557,2558,2561,2563],{"class":35,"line":138},[33,2559,2560],{"class":241},"        expected ",[33,2562,1452],{"class":273},[33,2564,2565],{"class":241}," delay;\n",[33,2567,2568,2571,2574,2577,2579,2581,2584,2586,2589],{"class":35,"line":144},[33,2569,2570],{"class":245},"        setTimeout",[33,2572,2573],{"class":241},"(tick, Math.",[33,2575,2576],{"class":245},"max",[33,2578,249],{"class":241},[33,2580,291],{"class":290},[33,2582,2583],{"class":241},", delay ",[33,2585,2541],{"class":273},[33,2587,2588],{"class":241}," drift));  ",[33,2590,2591],{"class":39},"\u002F\u002F correct for drift\n",[33,2593,2594],{"class":35,"line":150},[33,2595,794],{"class":241},[33,2597,2598,2601],{"class":35,"line":156},[33,2599,2600],{"class":245},"    setTimeout",[33,2602,2603],{"class":241},"(tick, delay);\n",[33,2605,2606],{"class":35,"line":161},[33,2607,1051],{"class":241},[33,2609,2610],{"class":35,"line":167},[33,2611,229],{"emptyLinePlaceholder":228},[33,2613,2614],{"class":35,"line":173},[33,2615,2616],{"class":39},"\u002F\u002F ── Microtasks can starve macrotasks (infinite loop) ──\n",[33,2618,2619],{"class":35,"line":179},[33,2620,2621],{"class":39},"\u002F\u002F A microtask that adds another microtask never lets macrotasks run.\n",[33,2623,2624],{"class":35,"line":184},[33,2625,2626],{"class":39},"\u002F\u002F Don't create infinite microtask chains.\n",[33,2628,2629],{"class":35,"line":190},[33,2630,229],{"emptyLinePlaceholder":228},[33,2632,2633],{"class":35,"line":196},[33,2634,2635],{"class":39},"\u002F\u002F ── `await` yields to the event loop (it's a microtask boundary) ──\n",[33,2637,2638,2640,2642,2645],{"class":35,"line":202},[33,2639,1749],{"class":273},[33,2641,1752],{"class":273},[33,2643,2644],{"class":245}," f",[33,2646,1394],{"class":241},[33,2648,2649,2651,2653,2655,2657],{"class":35,"line":208},[33,2650,485],{"class":241},[33,2652,246],{"class":245},[33,2654,249],{"class":241},[33,2656,492],{"class":252},[33,2658,256],{"class":241},[33,2660,2661,2664,2666,2668,2670,2672],{"class":35,"line":213},[33,2662,2663],{"class":273},"    await",[33,2665,1805],{"class":290},[33,2667,307],{"class":241},[33,2669,310],{"class":245},[33,2671,2117],{"class":241},[33,2673,2674],{"class":39},"\u002F\u002F yields — microtasks\u002Ftimers can run here\n",[33,2676,2677,2679,2681,2683,2685],{"class":35,"line":219},[33,2678,485],{"class":241},[33,2680,246],{"class":245},[33,2682,249],{"class":241},[33,2684,520],{"class":252},[33,2686,256],{"class":241},[33,2688,2689],{"class":35,"line":225},[33,2690,1051],{"class":241},[33,2692,2693,2696],{"class":35,"line":232},[33,2694,2695],{"class":245},"f",[33,2697,1501],{"class":241},[33,2699,2700,2702,2704,2706,2708],{"class":35,"line":238},[33,2701,242],{"class":241},[33,2703,246],{"class":245},[33,2705,249],{"class":241},[33,2707,556],{"class":252},[33,2709,256],{"class":241},[33,2711,2712],{"class":35,"line":259},[33,2713,2714],{"class":39},"\u002F\u002F Output: A, C, B (await suspends, C runs, then B resumes as a microtask)\n",[33,2716,2717],{"class":35,"line":264},[33,2718,229],{"emptyLinePlaceholder":228},[33,2720,2721],{"class":35,"line":296},[33,2722,2723],{"class":39},"\u002F\u002F ── `requestAnimationFrame` runs before paint, not on the event loop tick ──\n",[33,2725,2726],{"class":35,"line":301},[33,2727,2728],{"class":39},"\u002F\u002F rAF callbacks run in the render phase (after microtasks, before paint).\n",[33,2730,2731],{"class":35,"line":316},[33,2732,2733],{"class":39},"\u002F\u002F They're not macrotasks — they run at the browser's frame rate (~60fps).\n",[15,2735,2737],{"id":2736},"quick-quiz","🧠 Quick Quiz",[2739,2740,2741],"p",{},"What's the output order?",[20,2743,2744],{"language":22},[24,2745,2747],{"className":26,"code":2746,"language":22,"meta":28,"style":28},"console.log(\"1\");\nsetTimeout(() => console.log(\"2\"), 0);\nPromise.resolve().then(() => console.log(\"3\"));\nconsole.log(\"4\");\nqueueMicrotask(() => console.log(\"5\"));\n",[30,2748,2749,2762,2785,2812,2825],{"__ignoreMap":28},[33,2750,2751,2753,2755,2757,2760],{"class":35,"line":36},[33,2752,242],{"class":241},[33,2754,246],{"class":245},[33,2756,249],{"class":241},[33,2758,2759],{"class":252},"\"1\"",[33,2761,256],{"class":241},[33,2763,2764,2766,2768,2770,2772,2774,2776,2779,2781,2783],{"class":35,"line":43},[33,2765,267],{"class":245},[33,2767,270],{"class":241},[33,2769,274],{"class":273},[33,2771,277],{"class":241},[33,2773,246],{"class":245},[33,2775,249],{"class":241},[33,2777,2778],{"class":252},"\"2\"",[33,2780,287],{"class":241},[33,2782,291],{"class":290},[33,2784,256],{"class":241},[33,2786,2787,2789,2791,2793,2795,2797,2799,2801,2803,2805,2807,2810],{"class":35,"line":49},[33,2788,304],{"class":290},[33,2790,307],{"class":241},[33,2792,310],{"class":245},[33,2794,471],{"class":241},[33,2796,322],{"class":245},[33,2798,270],{"class":241},[33,2800,274],{"class":273},[33,2802,277],{"class":241},[33,2804,246],{"class":245},[33,2806,249],{"class":241},[33,2808,2809],{"class":252},"\"3\"",[33,2811,361],{"class":241},[33,2813,2814,2816,2818,2820,2823],{"class":35,"line":55},[33,2815,242],{"class":241},[33,2817,246],{"class":245},[33,2819,249],{"class":241},[33,2821,2822],{"class":252},"\"4\"",[33,2824,256],{"class":241},[33,2826,2827,2829,2831,2833,2835,2837,2839,2842],{"class":35,"line":61},[33,2828,372],{"class":245},[33,2830,270],{"class":241},[33,2832,274],{"class":273},[33,2834,277],{"class":241},[33,2836,246],{"class":245},[33,2838,249],{"class":241},[33,2840,2841],{"class":252},"\"5\"",[33,2843,361],{"class":241},[2845,2846,2847,2851,2859,2893],"details",{},[2848,2849,2850],"summary",{},"Answer",[24,2852,2857],{"className":2853,"code":2855,"language":2856},[2854],"language-text","1\n4\n3\n5\n2\n","text",[30,2858,2855],{"__ignoreMap":28},[2860,2861,2862,2869,2875,2881,2887],"ol",{},[2863,2864,2865,2868],"li",{},[30,2866,2867],{},"1"," — synchronous (script is the current macrotask)",[2863,2870,2871,2874],{},[30,2872,2873],{},"4"," — synchronous (continues)",[2863,2876,2877,2880],{},[30,2878,2879],{},"3"," — microtask (Promise.then — drained after script)",[2863,2882,2883,2886],{},[30,2884,2885],{},"5"," — microtask (queueMicrotask — same microtask drain)",[2863,2888,2889,2892],{},[30,2890,2891],{},"2"," — macrotask (setTimeout — runs after all microtasks are drained)",[2739,2894,2895,2899],{},[2896,2897,2898],"strong",{},"The lesson",": all microtasks (Promise.then, queueMicrotask) run before the next macrotask (setTimeout). The microtask queue is fully drained before the event loop proceeds to the next macrotask.",[2901,2902,2903],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":28,"searchDepth":43,"depth":43,"links":2905},[2906,2907,2908,2909,2911,2912,2913,2914],{"id":17,"depth":43,"text":18},{"id":438,"depth":43,"text":439},{"id":680,"depth":43,"text":681},{"id":1319,"depth":43,"text":2910},"Production Pattern: Concurrency with queueMicrotask",{"id":1634,"depth":43,"text":1635},{"id":2014,"depth":43,"text":2015},{"id":2358,"depth":43,"text":2359},{"id":2736,"depth":43,"text":2737},"Deep-dive into the JavaScript event loop: the call stack and heap, microtask vs macrotask queues, execution order guarantees, queueMicrotask, the task pipeline, and starvation patterns. Code-first reference for senior engineers.","md",{},"\u002Fjs\u002F15-callbacks-and-the-event-loop",{"title":5,"description":2915},"js\u002F15-callbacks-and-the-event-loop","DNqEWUnozvp9s8e4QJ1jF4igNC4zOvVvOqxOes8BKAs",1789924649314]