[{"data":1,"prerenderedAt":4372},["ShallowReactive",2],{"page-\u002Fjs\u002F16-promises":3},{"id":4,"title":5,"body":6,"description":4365,"extension":4366,"meta":4367,"navigation":105,"path":4368,"seo":4369,"stem":4370,"__hash__":4371},"content\u002Fjs\u002F16-promises.md","JavaScript 16 — Promise Internals: States, Chaining, Composition & Error Propagation",{"type":7,"value":8,"toc":4352},"minimark",[9,14,19,407,419,977,981,1404,1420,2012,2016,2591,2595,3179,3183,3691,3695,4107,4111,4115,4258,4348],[10,11,13],"h1",{"id":12},"_16-promise-internals-states-chaining-composition-error-propagation","16 — Promise Internals: States, Chaining, Composition & Error Propagation",[15,16,18],"h2",{"id":17},"the-promise-state-machine","The Promise State Machine",[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 ── A Promise is a state machine with exactly 3 states ──\n\u002F\u002F\n\u002F\u002F   ┌──────────┐     resolve()     ┌───────────┐\n\u002F\u002F   │ PENDING  │ ────────────────→ │ FULFILLED │  (has a value)\n\u002F\u002F   │          │                   └───────────┘\n\u002F\u002F   │          │                   ┌───────────┐\n\u002F\u002F   │          │ ──reject()───────→ │  REJECTED │  (has a reason\u002Ferror)\n\u002F\u002F   └──────────┘                   └───────────┘\n\u002F\u002F\n\u002F\u002F Transitions are ONE-WAY: once settled (fulfilled or rejected), a Promise can't change state.\n\u002F\u002F The value (or reason) is immutable after settlement.\n\n\u002F\u002F ── Creating a Promise ──\nconst pending = new Promise((resolve, reject) => {\n    \u002F\u002F The executor function runs SYNCHRONOUSLY when the Promise is created.\n    \u002F\u002F Call resolve(value) to fulfill, reject(error) to reject.\n    \u002F\u002F If neither is called, the Promise stays pending forever.\n    setTimeout(() => resolve(\"done\"), 1000);\n});\n\n\u002F\u002F ── A Promise that's already settled (immediate) ──\nconst fulfilled = Promise.resolve(42);  \u002F\u002F already fulfilled with 42\nconst rejected = Promise.reject(new Error(\"fail\"));  \u002F\u002F already rejected\n\n\u002F\u002F ── State transitions are permanent ──\nconst p = new Promise((resolve, reject) => {\n    resolve(\"first\");  \u002F\u002F fulfilled with \"first\"\n    resolve(\"second\"); \u002F\u002F IGNORED (already settled — can't change)\n    reject(\"error\");   \u002F\u002F IGNORED (already settled)\n});\np.then(v => console.log(v));  \u002F\u002F \"first\" (only the first settlement counts)\n","",[30,31,32,41,47,53,59,65,71,77,83,88,94,100,107,113,156,162,168,174,205,211,216,222,250,285,290,296,324,340,356,373,378],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sdCPZ","\u002F\u002F ── A Promise is a state machine with exactly 3 states ──\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   ┌──────────┐     resolve()     ┌───────────┐\n",[33,54,56],{"class":35,"line":55},4,[33,57,58],{"class":39},"\u002F\u002F   │ PENDING  │ ────────────────→ │ FULFILLED │  (has a value)\n",[33,60,62],{"class":35,"line":61},5,[33,63,64],{"class":39},"\u002F\u002F   │          │                   └───────────┘\n",[33,66,68],{"class":35,"line":67},6,[33,69,70],{"class":39},"\u002F\u002F   │          │                   ┌───────────┐\n",[33,72,74],{"class":35,"line":73},7,[33,75,76],{"class":39},"\u002F\u002F   │          │ ──reject()───────→ │  REJECTED │  (has a reason\u002Ferror)\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 Transitions are ONE-WAY: once settled (fulfilled or rejected), a Promise can't change state.\n",[33,95,97],{"class":35,"line":96},11,[33,98,99],{"class":39},"\u002F\u002F The value (or reason) is immutable after settlement.\n",[33,101,103],{"class":35,"line":102},12,[33,104,106],{"emptyLinePlaceholder":105},true,"\n",[33,108,110],{"class":35,"line":109},13,[33,111,112],{"class":39},"\u002F\u002F ── Creating a Promise ──\n",[33,114,116,120,124,127,130,133,137,141,144,147,150,153],{"class":35,"line":115},14,[33,117,119],{"class":118},"svdQ7","const",[33,121,123],{"class":122},"snvgF"," pending",[33,125,126],{"class":118}," =",[33,128,129],{"class":118}," new",[33,131,132],{"class":122}," Promise",[33,134,136],{"class":135},"ssxIu","((",[33,138,140],{"class":139},"sCrzJ","resolve",[33,142,143],{"class":135},", ",[33,145,146],{"class":139},"reject",[33,148,149],{"class":135},") ",[33,151,152],{"class":118},"=>",[33,154,155],{"class":135}," {\n",[33,157,159],{"class":35,"line":158},15,[33,160,161],{"class":39},"    \u002F\u002F The executor function runs SYNCHRONOUSLY when the Promise is created.\n",[33,163,165],{"class":35,"line":164},16,[33,166,167],{"class":39},"    \u002F\u002F Call resolve(value) to fulfill, reject(error) to reject.\n",[33,169,171],{"class":35,"line":170},17,[33,172,173],{"class":39},"    \u002F\u002F If neither is called, the Promise stays pending forever.\n",[33,175,177,181,184,186,189,192,196,199,202],{"class":35,"line":176},18,[33,178,180],{"class":179},"sIsaT","    setTimeout",[33,182,183],{"class":135},"(() ",[33,185,152],{"class":118},[33,187,188],{"class":179}," resolve",[33,190,191],{"class":135},"(",[33,193,195],{"class":194},"sJ6F3","\"done\"",[33,197,198],{"class":135},"), ",[33,200,201],{"class":122},"1000",[33,203,204],{"class":135},");\n",[33,206,208],{"class":35,"line":207},19,[33,209,210],{"class":135},"});\n",[33,212,214],{"class":35,"line":213},20,[33,215,106],{"emptyLinePlaceholder":105},[33,217,219],{"class":35,"line":218},21,[33,220,221],{"class":39},"\u002F\u002F ── A Promise that's already settled (immediate) ──\n",[33,223,225,227,230,232,234,237,239,241,244,247],{"class":35,"line":224},22,[33,226,119],{"class":118},[33,228,229],{"class":122}," fulfilled",[33,231,126],{"class":118},[33,233,132],{"class":122},[33,235,236],{"class":135},".",[33,238,140],{"class":179},[33,240,191],{"class":135},[33,242,243],{"class":122},"42",[33,245,246],{"class":135},");  ",[33,248,249],{"class":39},"\u002F\u002F already fulfilled with 42\n",[33,251,253,255,258,260,262,264,266,268,271,274,276,279,282],{"class":35,"line":252},23,[33,254,119],{"class":118},[33,256,257],{"class":122}," rejected",[33,259,126],{"class":118},[33,261,132],{"class":122},[33,263,236],{"class":135},[33,265,146],{"class":179},[33,267,191],{"class":135},[33,269,270],{"class":118},"new",[33,272,273],{"class":179}," Error",[33,275,191],{"class":135},[33,277,278],{"class":194},"\"fail\"",[33,280,281],{"class":135},"));  ",[33,283,284],{"class":39},"\u002F\u002F already rejected\n",[33,286,288],{"class":35,"line":287},24,[33,289,106],{"emptyLinePlaceholder":105},[33,291,293],{"class":35,"line":292},25,[33,294,295],{"class":39},"\u002F\u002F ── State transitions are permanent ──\n",[33,297,299,301,304,306,308,310,312,314,316,318,320,322],{"class":35,"line":298},26,[33,300,119],{"class":118},[33,302,303],{"class":122}," p",[33,305,126],{"class":118},[33,307,129],{"class":118},[33,309,132],{"class":122},[33,311,136],{"class":135},[33,313,140],{"class":139},[33,315,143],{"class":135},[33,317,146],{"class":139},[33,319,149],{"class":135},[33,321,152],{"class":118},[33,323,155],{"class":135},[33,325,327,330,332,335,337],{"class":35,"line":326},27,[33,328,329],{"class":179},"    resolve",[33,331,191],{"class":135},[33,333,334],{"class":194},"\"first\"",[33,336,246],{"class":135},[33,338,339],{"class":39},"\u002F\u002F fulfilled with \"first\"\n",[33,341,343,345,347,350,353],{"class":35,"line":342},28,[33,344,329],{"class":179},[33,346,191],{"class":135},[33,348,349],{"class":194},"\"second\"",[33,351,352],{"class":135},"); ",[33,354,355],{"class":39},"\u002F\u002F IGNORED (already settled — can't change)\n",[33,357,359,362,364,367,370],{"class":35,"line":358},29,[33,360,361],{"class":179},"    reject",[33,363,191],{"class":135},[33,365,366],{"class":194},"\"error\"",[33,368,369],{"class":135},");   ",[33,371,372],{"class":39},"\u002F\u002F IGNORED (already settled)\n",[33,374,376],{"class":35,"line":375},30,[33,377,210],{"class":135},[33,379,381,384,387,389,392,395,398,401,404],{"class":35,"line":380},31,[33,382,383],{"class":135},"p.",[33,385,386],{"class":179},"then",[33,388,191],{"class":135},[33,390,391],{"class":139},"v",[33,393,394],{"class":118}," =>",[33,396,397],{"class":135}," console.",[33,399,400],{"class":179},"log",[33,402,403],{"class":135},"(v));  ",[33,405,406],{"class":39},"\u002F\u002F \"first\" (only the first settlement counts)\n",[15,408,410,411,143,413,143,416],{"id":409},"chaining-then-catch-finally","Chaining: ",[30,412,386],{},[30,414,415],{},"catch",[30,417,418],{},"finally",[20,420,421],{"language":22},[24,422,424],{"className":26,"code":423,"language":22,"meta":28,"style":28},"\u002F\u002F ── .then(onFulfilled, onRejected) ──\n\u002F\u002F Returns a NEW Promise. The return value of the callback becomes the next Promise's value.\nPromise.resolve(1)\n    .then(v => v + 1)        \u002F\u002F returns 2 → next Promise is fulfilled with 2\n    .then(v => v * 3)        \u002F\u002F returns 6\n    .then(v => console.log(v));  \u002F\u002F logs 6\n\n\u002F\u002F ── Returning a Promise from .then (unwraps automatically) ──\nPromise.resolve(1)\n    .then(v => fetch(`\u002Fapi\u002F${v}`))  \u002F\u002F returns a Promise → unwrapped (waits for it)\n    .then(response => response.json())  \u002F\u002F returns another Promise → unwrapped\n    .then(data => console.log(data));   \u002F\u002F the resolved data\n\n\u002F\u002F ── .catch(onRejected) — shorthand for .then(null, onRejected) ──\nPromise.reject(new Error(\"fail\"))\n    .catch(err => console.log(\"caught:\", err.message));  \u002F\u002F \"caught: fail\"\n\n\u002F\u002F ── .finally(onSettled) — runs on both fulfill and reject (no value change) ──\nPromise.resolve(\"data\")\n    .finally(() => console.log(\"cleanup\"))  \u002F\u002F runs regardless (returns undefined → doesn't change value)\n    .then(v => console.log(\"value:\", v));    \u002F\u002F \"value: data\" (finally didn't change the value)\n\n\u002F\u002F ── Error propagation: rejected Promises skip .then and jump to .catch ──\nPromise.resolve()\n    .then(() => { throw new Error(\"boom\"); })  \u002F\u002F throws → Promise rejects\n    .then(() => console.log(\"skipped\"))        \u002F\u002F SKIPPED (previous rejected)\n    .catch(err => console.log(\"caught:\", err.message))  \u002F\u002F \"caught: boom\"\n    .then(() => console.log(\"after catch\"));   \u002F\u002F \"after catch\" (catch handled it → fulfilled)\n\n\u002F\u002F ── .then with onRejected (less readable than .catch) ──\nPromise.reject(\"error\")\n    .then(\n        v => console.log(\"fulfilled:\", v),\n        e => console.log(\"rejected:\", e)  \u002F\u002F handles rejection here\n    );\n\u002F\u002F Prefer .catch over the second arg to .then for readability.\n",[30,425,426,431,436,453,481,506,527,531,536,550,581,606,629,633,638,659,687,691,696,711,735,762,766,771,782,813,838,864,889,893,898,912,922,942,965,971],{"__ignoreMap":28},[33,427,428],{"class":35,"line":36},[33,429,430],{"class":39},"\u002F\u002F ── .then(onFulfilled, onRejected) ──\n",[33,432,433],{"class":35,"line":43},[33,434,435],{"class":39},"\u002F\u002F Returns a NEW Promise. The return value of the callback becomes the next Promise's value.\n",[33,437,438,441,443,445,447,450],{"class":35,"line":49},[33,439,440],{"class":122},"Promise",[33,442,236],{"class":135},[33,444,140],{"class":179},[33,446,191],{"class":135},[33,448,449],{"class":122},"1",[33,451,452],{"class":135},")\n",[33,454,455,458,460,462,464,466,469,472,475,478],{"class":35,"line":55},[33,456,457],{"class":135},"    .",[33,459,386],{"class":179},[33,461,191],{"class":135},[33,463,391],{"class":139},[33,465,394],{"class":118},[33,467,468],{"class":135}," v ",[33,470,471],{"class":118},"+",[33,473,474],{"class":122}," 1",[33,476,477],{"class":135},")        ",[33,479,480],{"class":39},"\u002F\u002F returns 2 → next Promise is fulfilled with 2\n",[33,482,483,485,487,489,491,493,495,498,501,503],{"class":35,"line":61},[33,484,457],{"class":135},[33,486,386],{"class":179},[33,488,191],{"class":135},[33,490,391],{"class":139},[33,492,394],{"class":118},[33,494,468],{"class":135},[33,496,497],{"class":118},"*",[33,499,500],{"class":122}," 3",[33,502,477],{"class":135},[33,504,505],{"class":39},"\u002F\u002F returns 6\n",[33,507,508,510,512,514,516,518,520,522,524],{"class":35,"line":67},[33,509,457],{"class":135},[33,511,386],{"class":179},[33,513,191],{"class":135},[33,515,391],{"class":139},[33,517,394],{"class":118},[33,519,397],{"class":135},[33,521,400],{"class":179},[33,523,403],{"class":135},[33,525,526],{"class":39},"\u002F\u002F logs 6\n",[33,528,529],{"class":35,"line":73},[33,530,106],{"emptyLinePlaceholder":105},[33,532,533],{"class":35,"line":79},[33,534,535],{"class":39},"\u002F\u002F ── Returning a Promise from .then (unwraps automatically) ──\n",[33,537,538,540,542,544,546,548],{"class":35,"line":85},[33,539,440],{"class":122},[33,541,236],{"class":135},[33,543,140],{"class":179},[33,545,191],{"class":135},[33,547,449],{"class":122},[33,549,452],{"class":135},[33,551,552,554,556,558,560,562,565,567,570,572,575,578],{"class":35,"line":90},[33,553,457],{"class":135},[33,555,386],{"class":179},[33,557,191],{"class":135},[33,559,391],{"class":139},[33,561,394],{"class":118},[33,563,564],{"class":179}," fetch",[33,566,191],{"class":135},[33,568,569],{"class":194},"`\u002Fapi\u002F${",[33,571,391],{"class":135},[33,573,574],{"class":194},"}`",[33,576,577],{"class":135},"))  ",[33,579,580],{"class":39},"\u002F\u002F returns a Promise → unwrapped (waits for it)\n",[33,582,583,585,587,589,592,594,597,600,603],{"class":35,"line":96},[33,584,457],{"class":135},[33,586,386],{"class":179},[33,588,191],{"class":135},[33,590,591],{"class":139},"response",[33,593,394],{"class":118},[33,595,596],{"class":135}," response.",[33,598,599],{"class":179},"json",[33,601,602],{"class":135},"())  ",[33,604,605],{"class":39},"\u002F\u002F returns another Promise → unwrapped\n",[33,607,608,610,612,614,617,619,621,623,626],{"class":35,"line":102},[33,609,457],{"class":135},[33,611,386],{"class":179},[33,613,191],{"class":135},[33,615,616],{"class":139},"data",[33,618,394],{"class":118},[33,620,397],{"class":135},[33,622,400],{"class":179},[33,624,625],{"class":135},"(data));   ",[33,627,628],{"class":39},"\u002F\u002F the resolved data\n",[33,630,631],{"class":35,"line":109},[33,632,106],{"emptyLinePlaceholder":105},[33,634,635],{"class":35,"line":115},[33,636,637],{"class":39},"\u002F\u002F ── .catch(onRejected) — shorthand for .then(null, onRejected) ──\n",[33,639,640,642,644,646,648,650,652,654,656],{"class":35,"line":158},[33,641,440],{"class":122},[33,643,236],{"class":135},[33,645,146],{"class":179},[33,647,191],{"class":135},[33,649,270],{"class":118},[33,651,273],{"class":179},[33,653,191],{"class":135},[33,655,278],{"class":194},[33,657,658],{"class":135},"))\n",[33,660,661,663,665,667,670,672,674,676,678,681,684],{"class":35,"line":164},[33,662,457],{"class":135},[33,664,415],{"class":179},[33,666,191],{"class":135},[33,668,669],{"class":139},"err",[33,671,394],{"class":118},[33,673,397],{"class":135},[33,675,400],{"class":179},[33,677,191],{"class":135},[33,679,680],{"class":194},"\"caught:\"",[33,682,683],{"class":135},", err.message));  ",[33,685,686],{"class":39},"\u002F\u002F \"caught: fail\"\n",[33,688,689],{"class":35,"line":170},[33,690,106],{"emptyLinePlaceholder":105},[33,692,693],{"class":35,"line":176},[33,694,695],{"class":39},"\u002F\u002F ── .finally(onSettled) — runs on both fulfill and reject (no value change) ──\n",[33,697,698,700,702,704,706,709],{"class":35,"line":207},[33,699,440],{"class":122},[33,701,236],{"class":135},[33,703,140],{"class":179},[33,705,191],{"class":135},[33,707,708],{"class":194},"\"data\"",[33,710,452],{"class":135},[33,712,713,715,717,719,721,723,725,727,730,732],{"class":35,"line":213},[33,714,457],{"class":135},[33,716,418],{"class":179},[33,718,183],{"class":135},[33,720,152],{"class":118},[33,722,397],{"class":135},[33,724,400],{"class":179},[33,726,191],{"class":135},[33,728,729],{"class":194},"\"cleanup\"",[33,731,577],{"class":135},[33,733,734],{"class":39},"\u002F\u002F runs regardless (returns undefined → doesn't change value)\n",[33,736,737,739,741,743,745,747,749,751,753,756,759],{"class":35,"line":218},[33,738,457],{"class":135},[33,740,386],{"class":179},[33,742,191],{"class":135},[33,744,391],{"class":139},[33,746,394],{"class":118},[33,748,397],{"class":135},[33,750,400],{"class":179},[33,752,191],{"class":135},[33,754,755],{"class":194},"\"value:\"",[33,757,758],{"class":135},", v));    ",[33,760,761],{"class":39},"\u002F\u002F \"value: data\" (finally didn't change the value)\n",[33,763,764],{"class":35,"line":224},[33,765,106],{"emptyLinePlaceholder":105},[33,767,768],{"class":35,"line":252},[33,769,770],{"class":39},"\u002F\u002F ── Error propagation: rejected Promises skip .then and jump to .catch ──\n",[33,772,773,775,777,779],{"class":35,"line":287},[33,774,440],{"class":122},[33,776,236],{"class":135},[33,778,140],{"class":179},[33,780,781],{"class":135},"()\n",[33,783,784,786,788,790,792,795,798,800,802,804,807,810],{"class":35,"line":292},[33,785,457],{"class":135},[33,787,386],{"class":179},[33,789,183],{"class":135},[33,791,152],{"class":118},[33,793,794],{"class":135}," { ",[33,796,797],{"class":118},"throw",[33,799,129],{"class":118},[33,801,273],{"class":179},[33,803,191],{"class":135},[33,805,806],{"class":194},"\"boom\"",[33,808,809],{"class":135},"); })  ",[33,811,812],{"class":39},"\u002F\u002F throws → Promise rejects\n",[33,814,815,817,819,821,823,825,827,829,832,835],{"class":35,"line":298},[33,816,457],{"class":135},[33,818,386],{"class":179},[33,820,183],{"class":135},[33,822,152],{"class":118},[33,824,397],{"class":135},[33,826,400],{"class":179},[33,828,191],{"class":135},[33,830,831],{"class":194},"\"skipped\"",[33,833,834],{"class":135},"))        ",[33,836,837],{"class":39},"\u002F\u002F SKIPPED (previous rejected)\n",[33,839,840,842,844,846,848,850,852,854,856,858,861],{"class":35,"line":326},[33,841,457],{"class":135},[33,843,415],{"class":179},[33,845,191],{"class":135},[33,847,669],{"class":139},[33,849,394],{"class":118},[33,851,397],{"class":135},[33,853,400],{"class":179},[33,855,191],{"class":135},[33,857,680],{"class":194},[33,859,860],{"class":135},", err.message))  ",[33,862,863],{"class":39},"\u002F\u002F \"caught: boom\"\n",[33,865,866,868,870,872,874,876,878,880,883,886],{"class":35,"line":342},[33,867,457],{"class":135},[33,869,386],{"class":179},[33,871,183],{"class":135},[33,873,152],{"class":118},[33,875,397],{"class":135},[33,877,400],{"class":179},[33,879,191],{"class":135},[33,881,882],{"class":194},"\"after catch\"",[33,884,885],{"class":135},"));   ",[33,887,888],{"class":39},"\u002F\u002F \"after catch\" (catch handled it → fulfilled)\n",[33,890,891],{"class":35,"line":358},[33,892,106],{"emptyLinePlaceholder":105},[33,894,895],{"class":35,"line":375},[33,896,897],{"class":39},"\u002F\u002F ── .then with onRejected (less readable than .catch) ──\n",[33,899,900,902,904,906,908,910],{"class":35,"line":380},[33,901,440],{"class":122},[33,903,236],{"class":135},[33,905,146],{"class":179},[33,907,191],{"class":135},[33,909,366],{"class":194},[33,911,452],{"class":135},[33,913,915,917,919],{"class":35,"line":914},32,[33,916,457],{"class":135},[33,918,386],{"class":179},[33,920,921],{"class":135},"(\n",[33,923,925,928,930,932,934,936,939],{"class":35,"line":924},33,[33,926,927],{"class":139},"        v",[33,929,394],{"class":118},[33,931,397],{"class":135},[33,933,400],{"class":179},[33,935,191],{"class":135},[33,937,938],{"class":194},"\"fulfilled:\"",[33,940,941],{"class":135},", v),\n",[33,943,945,948,950,952,954,956,959,962],{"class":35,"line":944},34,[33,946,947],{"class":139},"        e",[33,949,394],{"class":118},[33,951,397],{"class":135},[33,953,400],{"class":179},[33,955,191],{"class":135},[33,957,958],{"class":194},"\"rejected:\"",[33,960,961],{"class":135},", e)  ",[33,963,964],{"class":39},"\u002F\u002F handles rejection here\n",[33,966,968],{"class":35,"line":967},35,[33,969,970],{"class":135},"    );\n",[33,972,974],{"class":35,"line":973},36,[33,975,976],{"class":39},"\u002F\u002F Prefer .catch over the second arg to .then for readability.\n",[15,978,980],{"id":979},"anti-pattern-nested-promises-pyramid-of-doom","Anti-Pattern: Nested Promises (Pyramid of Doom)",[20,982,983],{"language":22},[24,984,986],{"className":26,"code":985,"language":22,"meta":28,"style":28},"\u002F\u002F ❌ NAIVE — nesting Promises (callback hell with Promises)\nfetch(\"\u002Fapi\u002Fuser\u002F1\")\n    .then(user => {\n        fetch(`\u002Fapi\u002Fposts?userId=${user.id}`)\n            .then(posts => {\n                fetch(`\u002Fapi\u002Fcomments?postId=${posts[0].id}`)\n                    .then(comments => {\n                        console.log(comments);\n                    });\n            });\n    });\n\n\u002F\u002F ✅ CORRECT — chain with return (each .then unwraps the returned Promise)\nfetch(\"\u002Fapi\u002Fuser\u002F1\")\n    .then(user => fetch(`\u002Fapi\u002Fposts?userId=${user.id}`))\n    .then(posts => fetch(`\u002Fapi\u002Fcomments?postId=${posts[0].id}`))\n    .then(comments => console.log(comments))\n    .catch(err => console.error(\"error:\", err));\n\u002F\u002F Each .then returns a Promise → the next .then waits for it (flat chain, no nesting).\n\n\u002F\u002F ✅ BEST — async\u002Fawait (syntactic sugar over Promise chains)\nasync function loadData() {\n    try {\n        const user = await fetch(\"\u002Fapi\u002Fuser\u002F1\");\n        const posts = await fetch(`\u002Fapi\u002Fposts?userId=${user.id}`);\n        const comments = await fetch(`\u002Fapi\u002Fcomments?postId=${posts[0].id}`);\n        console.log(comments);\n    } catch (err) {\n        console.error(\"error:\", err);\n    }\n}\n",[30,987,988,993,1005,1020,1041,1057,1084,1100,1110,1115,1120,1125,1129,1134,1144,1172,1204,1223,1248,1253,1257,1262,1276,1283,1304,1331,1362,1371,1381,1394,1399],{"__ignoreMap":28},[33,989,990],{"class":35,"line":36},[33,991,992],{"class":39},"\u002F\u002F ❌ NAIVE — nesting Promises (callback hell with Promises)\n",[33,994,995,998,1000,1003],{"class":35,"line":43},[33,996,997],{"class":179},"fetch",[33,999,191],{"class":135},[33,1001,1002],{"class":194},"\"\u002Fapi\u002Fuser\u002F1\"",[33,1004,452],{"class":135},[33,1006,1007,1009,1011,1013,1016,1018],{"class":35,"line":49},[33,1008,457],{"class":135},[33,1010,386],{"class":179},[33,1012,191],{"class":135},[33,1014,1015],{"class":139},"user",[33,1017,394],{"class":118},[33,1019,155],{"class":135},[33,1021,1022,1025,1027,1030,1032,1034,1037,1039],{"class":35,"line":55},[33,1023,1024],{"class":179},"        fetch",[33,1026,191],{"class":135},[33,1028,1029],{"class":194},"`\u002Fapi\u002Fposts?userId=${",[33,1031,1015],{"class":135},[33,1033,236],{"class":194},[33,1035,1036],{"class":135},"id",[33,1038,574],{"class":194},[33,1040,452],{"class":135},[33,1042,1043,1046,1048,1050,1053,1055],{"class":35,"line":61},[33,1044,1045],{"class":135},"            .",[33,1047,386],{"class":179},[33,1049,191],{"class":135},[33,1051,1052],{"class":139},"posts",[33,1054,394],{"class":118},[33,1056,155],{"class":135},[33,1058,1059,1062,1064,1067,1069,1072,1075,1078,1080,1082],{"class":35,"line":67},[33,1060,1061],{"class":179},"                fetch",[33,1063,191],{"class":135},[33,1065,1066],{"class":194},"`\u002Fapi\u002Fcomments?postId=${",[33,1068,1052],{"class":135},[33,1070,1071],{"class":194},"[",[33,1073,1074],{"class":122},"0",[33,1076,1077],{"class":194},"].",[33,1079,1036],{"class":135},[33,1081,574],{"class":194},[33,1083,452],{"class":135},[33,1085,1086,1089,1091,1093,1096,1098],{"class":35,"line":73},[33,1087,1088],{"class":135},"                    .",[33,1090,386],{"class":179},[33,1092,191],{"class":135},[33,1094,1095],{"class":139},"comments",[33,1097,394],{"class":118},[33,1099,155],{"class":135},[33,1101,1102,1105,1107],{"class":35,"line":79},[33,1103,1104],{"class":135},"                        console.",[33,1106,400],{"class":179},[33,1108,1109],{"class":135},"(comments);\n",[33,1111,1112],{"class":35,"line":85},[33,1113,1114],{"class":135},"                    });\n",[33,1116,1117],{"class":35,"line":90},[33,1118,1119],{"class":135},"            });\n",[33,1121,1122],{"class":35,"line":96},[33,1123,1124],{"class":135},"    });\n",[33,1126,1127],{"class":35,"line":102},[33,1128,106],{"emptyLinePlaceholder":105},[33,1130,1131],{"class":35,"line":109},[33,1132,1133],{"class":39},"\u002F\u002F ✅ CORRECT — chain with return (each .then unwraps the returned Promise)\n",[33,1135,1136,1138,1140,1142],{"class":35,"line":115},[33,1137,997],{"class":179},[33,1139,191],{"class":135},[33,1141,1002],{"class":194},[33,1143,452],{"class":135},[33,1145,1146,1148,1150,1152,1154,1156,1158,1160,1162,1164,1166,1168,1170],{"class":35,"line":158},[33,1147,457],{"class":135},[33,1149,386],{"class":179},[33,1151,191],{"class":135},[33,1153,1015],{"class":139},[33,1155,394],{"class":118},[33,1157,564],{"class":179},[33,1159,191],{"class":135},[33,1161,1029],{"class":194},[33,1163,1015],{"class":135},[33,1165,236],{"class":194},[33,1167,1036],{"class":135},[33,1169,574],{"class":194},[33,1171,658],{"class":135},[33,1173,1174,1176,1178,1180,1182,1184,1186,1188,1190,1192,1194,1196,1198,1200,1202],{"class":35,"line":164},[33,1175,457],{"class":135},[33,1177,386],{"class":179},[33,1179,191],{"class":135},[33,1181,1052],{"class":139},[33,1183,394],{"class":118},[33,1185,564],{"class":179},[33,1187,191],{"class":135},[33,1189,1066],{"class":194},[33,1191,1052],{"class":135},[33,1193,1071],{"class":194},[33,1195,1074],{"class":122},[33,1197,1077],{"class":194},[33,1199,1036],{"class":135},[33,1201,574],{"class":194},[33,1203,658],{"class":135},[33,1205,1206,1208,1210,1212,1214,1216,1218,1220],{"class":35,"line":170},[33,1207,457],{"class":135},[33,1209,386],{"class":179},[33,1211,191],{"class":135},[33,1213,1095],{"class":139},[33,1215,394],{"class":118},[33,1217,397],{"class":135},[33,1219,400],{"class":179},[33,1221,1222],{"class":135},"(comments))\n",[33,1224,1225,1227,1229,1231,1233,1235,1237,1240,1242,1245],{"class":35,"line":176},[33,1226,457],{"class":135},[33,1228,415],{"class":179},[33,1230,191],{"class":135},[33,1232,669],{"class":139},[33,1234,394],{"class":118},[33,1236,397],{"class":135},[33,1238,1239],{"class":179},"error",[33,1241,191],{"class":135},[33,1243,1244],{"class":194},"\"error:\"",[33,1246,1247],{"class":135},", err));\n",[33,1249,1250],{"class":35,"line":207},[33,1251,1252],{"class":39},"\u002F\u002F Each .then returns a Promise → the next .then waits for it (flat chain, no nesting).\n",[33,1254,1255],{"class":35,"line":213},[33,1256,106],{"emptyLinePlaceholder":105},[33,1258,1259],{"class":35,"line":218},[33,1260,1261],{"class":39},"\u002F\u002F ✅ BEST — async\u002Fawait (syntactic sugar over Promise chains)\n",[33,1263,1264,1267,1270,1273],{"class":35,"line":224},[33,1265,1266],{"class":118},"async",[33,1268,1269],{"class":118}," function",[33,1271,1272],{"class":179}," loadData",[33,1274,1275],{"class":135},"() {\n",[33,1277,1278,1281],{"class":35,"line":252},[33,1279,1280],{"class":118},"    try",[33,1282,155],{"class":135},[33,1284,1285,1288,1291,1293,1296,1298,1300,1302],{"class":35,"line":287},[33,1286,1287],{"class":118},"        const",[33,1289,1290],{"class":122}," user",[33,1292,126],{"class":118},[33,1294,1295],{"class":118}," await",[33,1297,564],{"class":179},[33,1299,191],{"class":135},[33,1301,1002],{"class":194},[33,1303,204],{"class":135},[33,1305,1306,1308,1311,1313,1315,1317,1319,1321,1323,1325,1327,1329],{"class":35,"line":292},[33,1307,1287],{"class":118},[33,1309,1310],{"class":122}," posts",[33,1312,126],{"class":118},[33,1314,1295],{"class":118},[33,1316,564],{"class":179},[33,1318,191],{"class":135},[33,1320,1029],{"class":194},[33,1322,1015],{"class":135},[33,1324,236],{"class":194},[33,1326,1036],{"class":135},[33,1328,574],{"class":194},[33,1330,204],{"class":135},[33,1332,1333,1335,1338,1340,1342,1344,1346,1348,1350,1352,1354,1356,1358,1360],{"class":35,"line":298},[33,1334,1287],{"class":118},[33,1336,1337],{"class":122}," comments",[33,1339,126],{"class":118},[33,1341,1295],{"class":118},[33,1343,564],{"class":179},[33,1345,191],{"class":135},[33,1347,1066],{"class":194},[33,1349,1052],{"class":135},[33,1351,1071],{"class":194},[33,1353,1074],{"class":122},[33,1355,1077],{"class":194},[33,1357,1036],{"class":135},[33,1359,574],{"class":194},[33,1361,204],{"class":135},[33,1363,1364,1367,1369],{"class":35,"line":326},[33,1365,1366],{"class":135},"        console.",[33,1368,400],{"class":179},[33,1370,1109],{"class":135},[33,1372,1373,1376,1378],{"class":35,"line":342},[33,1374,1375],{"class":135},"    } ",[33,1377,415],{"class":118},[33,1379,1380],{"class":135}," (err) {\n",[33,1382,1383,1385,1387,1389,1391],{"class":35,"line":358},[33,1384,1366],{"class":135},[33,1386,1239],{"class":179},[33,1388,191],{"class":135},[33,1390,1244],{"class":194},[33,1392,1393],{"class":135},", err);\n",[33,1395,1396],{"class":35,"line":375},[33,1397,1398],{"class":135},"    }\n",[33,1400,1401],{"class":35,"line":380},[33,1402,1403],{"class":135},"}\n",[15,1405,1407,1408,143,1411,143,1414,143,1417],{"id":1406},"promise-composition-all-race-allsettled-any","Promise Composition: ",[30,1409,1410],{},"all",[30,1412,1413],{},"race",[30,1415,1416],{},"allSettled",[30,1418,1419],{},"any",[20,1421,1422],{"language":22},[24,1423,1425],{"className":26,"code":1424,"language":22,"meta":28,"style":28},"\u002F\u002F ── Promise.all: wait for ALL to fulfill (or first rejection) ──\n\u002F\u002F Returns an array of results in the same order as the input.\nconst [user, posts] = await Promise.all([\n    fetch(\"\u002Fapi\u002Fuser\").then(r => r.json()),\n    fetch(\"\u002Fapi\u002Fposts\").then(r => r.json()),\n]);\n\u002F\u002F If ANY rejects, the whole Promise.all rejects immediately (others keep running but ignored).\n\n\u002F\u002F ── Promise.race: first to settle (fulfill or reject) wins ──\nconst fastest = await Promise.race([\n    fetch(\"\u002Fapi\u002Ffast\"),\n    fetch(\"\u002Fapi\u002Fslow\"),\n    new Promise((_, reject) => setTimeout(() => reject(new Error(\"timeout\")), 5000)),\n]);\n\u002F\u002F The first Promise to settle (fulfill or reject) determines the result.\n\n\u002F\u002F ── Promise.allSettled: wait for ALL, never rejects (returns status for each) ──\nconst results = await Promise.allSettled([\n    fetch(\"\u002Fapi\u002Fa\").then(r => r.json()),\n    fetch(\"\u002Fapi\u002Fb\").then(r => r.json()),\n    fetch(\"\u002Fapi\u002Fbroken\").then(r => r.json()),\n]);\n\u002F\u002F [\n\u002F\u002F   { status: \"fulfilled\", value: dataA },\n\u002F\u002F   { status: \"fulfilled\", value: dataB },\n\u002F\u002F   { status: \"rejected\", reason: errorC },\n\u002F\u002F ]\nfor (const r of results) {\n    if (r.status === \"fulfilled\") console.log(\"ok:\", r.value);\n    else console.log(\"error:\", r.reason);\n}\n\n\u002F\u002F ── Promise.any: first to FULFILL wins (ignores rejections) ──\nconst firstSuccess = await Promise.any([\n    fetch(\"\u002Fapi\u002Fprimary\").then(r => r.json()),     \u002F\u002F might fail\n    fetch(\"\u002Fapi\u002Ffallback1\").then(r => r.json()),    \u002F\u002F might fail\n    fetch(\"\u002Fapi\u002Ffallback2\").then(r => r.json()),    \u002F\u002F succeeds → this wins\n]);\n\u002F\u002F If ALL reject, Promise.any rejects with AggregateError (all errors).\n\n\u002F\u002F ── Comparison table ──\n\u002F\u002F | Method       | Waits for   | Rejects if          | Returns                     |\n\u002F\u002F |-------------|-------------|---------------------|-----------------------------|\n\u002F\u002F | all         | All fulfill | Any rejects         | Array of values (ordered)   |\n\u002F\u002F | race        | First settle| First rejects       | First value or error         |\n\u002F\u002F | allSettled  | All settle  | Never rejects       | Array of {status, value\u002Freason} |\n\u002F\u002F | any         | First fulfill| All reject         | First value (AggregateError if all fail) |\n",[30,1426,1427,1432,1437,1467,1497,1522,1527,1532,1536,1541,1560,1572,1583,1633,1637,1642,1646,1651,1670,1695,1720,1745,1749,1754,1759,1764,1769,1774,1793,1820,1836,1840,1844,1849,1868,1897,1925,1954,1959,1965,1970,1976,1982,1988,1994,2000,2006],{"__ignoreMap":28},[33,1428,1429],{"class":35,"line":36},[33,1430,1431],{"class":39},"\u002F\u002F ── Promise.all: wait for ALL to fulfill (or first rejection) ──\n",[33,1433,1434],{"class":35,"line":43},[33,1435,1436],{"class":39},"\u002F\u002F Returns an array of results in the same order as the input.\n",[33,1438,1439,1441,1444,1446,1448,1450,1453,1456,1458,1460,1462,1464],{"class":35,"line":49},[33,1440,119],{"class":118},[33,1442,1443],{"class":135}," [",[33,1445,1015],{"class":122},[33,1447,143],{"class":135},[33,1449,1052],{"class":122},[33,1451,1452],{"class":135},"] ",[33,1454,1455],{"class":118},"=",[33,1457,1295],{"class":118},[33,1459,132],{"class":122},[33,1461,236],{"class":135},[33,1463,1410],{"class":179},[33,1465,1466],{"class":135},"([\n",[33,1468,1469,1472,1474,1477,1480,1482,1484,1487,1489,1492,1494],{"class":35,"line":55},[33,1470,1471],{"class":179},"    fetch",[33,1473,191],{"class":135},[33,1475,1476],{"class":194},"\"\u002Fapi\u002Fuser\"",[33,1478,1479],{"class":135},").",[33,1481,386],{"class":179},[33,1483,191],{"class":135},[33,1485,1486],{"class":139},"r",[33,1488,394],{"class":118},[33,1490,1491],{"class":135}," r.",[33,1493,599],{"class":179},[33,1495,1496],{"class":135},"()),\n",[33,1498,1499,1501,1503,1506,1508,1510,1512,1514,1516,1518,1520],{"class":35,"line":61},[33,1500,1471],{"class":179},[33,1502,191],{"class":135},[33,1504,1505],{"class":194},"\"\u002Fapi\u002Fposts\"",[33,1507,1479],{"class":135},[33,1509,386],{"class":179},[33,1511,191],{"class":135},[33,1513,1486],{"class":139},[33,1515,394],{"class":118},[33,1517,1491],{"class":135},[33,1519,599],{"class":179},[33,1521,1496],{"class":135},[33,1523,1524],{"class":35,"line":67},[33,1525,1526],{"class":135},"]);\n",[33,1528,1529],{"class":35,"line":73},[33,1530,1531],{"class":39},"\u002F\u002F If ANY rejects, the whole Promise.all rejects immediately (others keep running but ignored).\n",[33,1533,1534],{"class":35,"line":79},[33,1535,106],{"emptyLinePlaceholder":105},[33,1537,1538],{"class":35,"line":85},[33,1539,1540],{"class":39},"\u002F\u002F ── Promise.race: first to settle (fulfill or reject) wins ──\n",[33,1542,1543,1545,1548,1550,1552,1554,1556,1558],{"class":35,"line":90},[33,1544,119],{"class":118},[33,1546,1547],{"class":122}," fastest",[33,1549,126],{"class":118},[33,1551,1295],{"class":118},[33,1553,132],{"class":122},[33,1555,236],{"class":135},[33,1557,1413],{"class":179},[33,1559,1466],{"class":135},[33,1561,1562,1564,1566,1569],{"class":35,"line":96},[33,1563,1471],{"class":179},[33,1565,191],{"class":135},[33,1567,1568],{"class":194},"\"\u002Fapi\u002Ffast\"",[33,1570,1571],{"class":135},"),\n",[33,1573,1574,1576,1578,1581],{"class":35,"line":102},[33,1575,1471],{"class":179},[33,1577,191],{"class":135},[33,1579,1580],{"class":194},"\"\u002Fapi\u002Fslow\"",[33,1582,1571],{"class":135},[33,1584,1585,1588,1590,1592,1595,1597,1599,1601,1603,1606,1608,1610,1613,1615,1617,1619,1621,1624,1627,1630],{"class":35,"line":109},[33,1586,1587],{"class":118},"    new",[33,1589,132],{"class":122},[33,1591,136],{"class":135},[33,1593,1594],{"class":139},"_",[33,1596,143],{"class":135},[33,1598,146],{"class":139},[33,1600,149],{"class":135},[33,1602,152],{"class":118},[33,1604,1605],{"class":179}," setTimeout",[33,1607,183],{"class":135},[33,1609,152],{"class":118},[33,1611,1612],{"class":179}," reject",[33,1614,191],{"class":135},[33,1616,270],{"class":118},[33,1618,273],{"class":179},[33,1620,191],{"class":135},[33,1622,1623],{"class":194},"\"timeout\"",[33,1625,1626],{"class":135},")), ",[33,1628,1629],{"class":122},"5000",[33,1631,1632],{"class":135},")),\n",[33,1634,1635],{"class":35,"line":115},[33,1636,1526],{"class":135},[33,1638,1639],{"class":35,"line":158},[33,1640,1641],{"class":39},"\u002F\u002F The first Promise to settle (fulfill or reject) determines the result.\n",[33,1643,1644],{"class":35,"line":164},[33,1645,106],{"emptyLinePlaceholder":105},[33,1647,1648],{"class":35,"line":170},[33,1649,1650],{"class":39},"\u002F\u002F ── Promise.allSettled: wait for ALL, never rejects (returns status for each) ──\n",[33,1652,1653,1655,1658,1660,1662,1664,1666,1668],{"class":35,"line":176},[33,1654,119],{"class":118},[33,1656,1657],{"class":122}," results",[33,1659,126],{"class":118},[33,1661,1295],{"class":118},[33,1663,132],{"class":122},[33,1665,236],{"class":135},[33,1667,1416],{"class":179},[33,1669,1466],{"class":135},[33,1671,1672,1674,1676,1679,1681,1683,1685,1687,1689,1691,1693],{"class":35,"line":207},[33,1673,1471],{"class":179},[33,1675,191],{"class":135},[33,1677,1678],{"class":194},"\"\u002Fapi\u002Fa\"",[33,1680,1479],{"class":135},[33,1682,386],{"class":179},[33,1684,191],{"class":135},[33,1686,1486],{"class":139},[33,1688,394],{"class":118},[33,1690,1491],{"class":135},[33,1692,599],{"class":179},[33,1694,1496],{"class":135},[33,1696,1697,1699,1701,1704,1706,1708,1710,1712,1714,1716,1718],{"class":35,"line":213},[33,1698,1471],{"class":179},[33,1700,191],{"class":135},[33,1702,1703],{"class":194},"\"\u002Fapi\u002Fb\"",[33,1705,1479],{"class":135},[33,1707,386],{"class":179},[33,1709,191],{"class":135},[33,1711,1486],{"class":139},[33,1713,394],{"class":118},[33,1715,1491],{"class":135},[33,1717,599],{"class":179},[33,1719,1496],{"class":135},[33,1721,1722,1724,1726,1729,1731,1733,1735,1737,1739,1741,1743],{"class":35,"line":218},[33,1723,1471],{"class":179},[33,1725,191],{"class":135},[33,1727,1728],{"class":194},"\"\u002Fapi\u002Fbroken\"",[33,1730,1479],{"class":135},[33,1732,386],{"class":179},[33,1734,191],{"class":135},[33,1736,1486],{"class":139},[33,1738,394],{"class":118},[33,1740,1491],{"class":135},[33,1742,599],{"class":179},[33,1744,1496],{"class":135},[33,1746,1747],{"class":35,"line":224},[33,1748,1526],{"class":135},[33,1750,1751],{"class":35,"line":252},[33,1752,1753],{"class":39},"\u002F\u002F [\n",[33,1755,1756],{"class":35,"line":287},[33,1757,1758],{"class":39},"\u002F\u002F   { status: \"fulfilled\", value: dataA },\n",[33,1760,1761],{"class":35,"line":292},[33,1762,1763],{"class":39},"\u002F\u002F   { status: \"fulfilled\", value: dataB },\n",[33,1765,1766],{"class":35,"line":298},[33,1767,1768],{"class":39},"\u002F\u002F   { status: \"rejected\", reason: errorC },\n",[33,1770,1771],{"class":35,"line":326},[33,1772,1773],{"class":39},"\u002F\u002F ]\n",[33,1775,1776,1779,1782,1784,1787,1790],{"class":35,"line":342},[33,1777,1778],{"class":118},"for",[33,1780,1781],{"class":135}," (",[33,1783,119],{"class":118},[33,1785,1786],{"class":122}," r",[33,1788,1789],{"class":118}," of",[33,1791,1792],{"class":135}," results) {\n",[33,1794,1795,1798,1801,1804,1807,1810,1812,1814,1817],{"class":35,"line":358},[33,1796,1797],{"class":118},"    if",[33,1799,1800],{"class":135}," (r.status ",[33,1802,1803],{"class":118},"===",[33,1805,1806],{"class":194}," \"fulfilled\"",[33,1808,1809],{"class":135},") console.",[33,1811,400],{"class":179},[33,1813,191],{"class":135},[33,1815,1816],{"class":194},"\"ok:\"",[33,1818,1819],{"class":135},", r.value);\n",[33,1821,1822,1825,1827,1829,1831,1833],{"class":35,"line":375},[33,1823,1824],{"class":118},"    else",[33,1826,397],{"class":135},[33,1828,400],{"class":179},[33,1830,191],{"class":135},[33,1832,1244],{"class":194},[33,1834,1835],{"class":135},", r.reason);\n",[33,1837,1838],{"class":35,"line":380},[33,1839,1403],{"class":135},[33,1841,1842],{"class":35,"line":914},[33,1843,106],{"emptyLinePlaceholder":105},[33,1845,1846],{"class":35,"line":924},[33,1847,1848],{"class":39},"\u002F\u002F ── Promise.any: first to FULFILL wins (ignores rejections) ──\n",[33,1850,1851,1853,1856,1858,1860,1862,1864,1866],{"class":35,"line":944},[33,1852,119],{"class":118},[33,1854,1855],{"class":122}," firstSuccess",[33,1857,126],{"class":118},[33,1859,1295],{"class":118},[33,1861,132],{"class":122},[33,1863,236],{"class":135},[33,1865,1419],{"class":179},[33,1867,1466],{"class":135},[33,1869,1870,1872,1874,1877,1879,1881,1883,1885,1887,1889,1891,1894],{"class":35,"line":967},[33,1871,1471],{"class":179},[33,1873,191],{"class":135},[33,1875,1876],{"class":194},"\"\u002Fapi\u002Fprimary\"",[33,1878,1479],{"class":135},[33,1880,386],{"class":179},[33,1882,191],{"class":135},[33,1884,1486],{"class":139},[33,1886,394],{"class":118},[33,1888,1491],{"class":135},[33,1890,599],{"class":179},[33,1892,1893],{"class":135},"()),     ",[33,1895,1896],{"class":39},"\u002F\u002F might fail\n",[33,1898,1899,1901,1903,1906,1908,1910,1912,1914,1916,1918,1920,1923],{"class":35,"line":973},[33,1900,1471],{"class":179},[33,1902,191],{"class":135},[33,1904,1905],{"class":194},"\"\u002Fapi\u002Ffallback1\"",[33,1907,1479],{"class":135},[33,1909,386],{"class":179},[33,1911,191],{"class":135},[33,1913,1486],{"class":139},[33,1915,394],{"class":118},[33,1917,1491],{"class":135},[33,1919,599],{"class":179},[33,1921,1922],{"class":135},"()),    ",[33,1924,1896],{"class":39},[33,1926,1928,1930,1932,1935,1937,1939,1941,1943,1945,1947,1949,1951],{"class":35,"line":1927},37,[33,1929,1471],{"class":179},[33,1931,191],{"class":135},[33,1933,1934],{"class":194},"\"\u002Fapi\u002Ffallback2\"",[33,1936,1479],{"class":135},[33,1938,386],{"class":179},[33,1940,191],{"class":135},[33,1942,1486],{"class":139},[33,1944,394],{"class":118},[33,1946,1491],{"class":135},[33,1948,599],{"class":179},[33,1950,1922],{"class":135},[33,1952,1953],{"class":39},"\u002F\u002F succeeds → this wins\n",[33,1955,1957],{"class":35,"line":1956},38,[33,1958,1526],{"class":135},[33,1960,1962],{"class":35,"line":1961},39,[33,1963,1964],{"class":39},"\u002F\u002F If ALL reject, Promise.any rejects with AggregateError (all errors).\n",[33,1966,1968],{"class":35,"line":1967},40,[33,1969,106],{"emptyLinePlaceholder":105},[33,1971,1973],{"class":35,"line":1972},41,[33,1974,1975],{"class":39},"\u002F\u002F ── Comparison table ──\n",[33,1977,1979],{"class":35,"line":1978},42,[33,1980,1981],{"class":39},"\u002F\u002F | Method       | Waits for   | Rejects if          | Returns                     |\n",[33,1983,1985],{"class":35,"line":1984},43,[33,1986,1987],{"class":39},"\u002F\u002F |-------------|-------------|---------------------|-----------------------------|\n",[33,1989,1991],{"class":35,"line":1990},44,[33,1992,1993],{"class":39},"\u002F\u002F | all         | All fulfill | Any rejects         | Array of values (ordered)   |\n",[33,1995,1997],{"class":35,"line":1996},45,[33,1998,1999],{"class":39},"\u002F\u002F | race        | First settle| First rejects       | First value or error         |\n",[33,2001,2003],{"class":35,"line":2002},46,[33,2004,2005],{"class":39},"\u002F\u002F | allSettled  | All settle  | Never rejects       | Array of {status, value\u002Freason} |\n",[33,2007,2009],{"class":35,"line":2008},47,[33,2010,2011],{"class":39},"\u002F\u002F | any         | First fulfill| All reject         | First value (AggregateError if all fail) |\n",[15,2013,2015],{"id":2014},"error-propagation-and-recovery","Error Propagation and Recovery",[20,2017,2018],{"language":22},[24,2019,2021],{"className":26,"code":2020,"language":22,"meta":28,"style":28},"\u002F\u002F ── Errors skip .then handlers and propagate to .catch ──\nPromise.resolve()\n    .then(() => { throw new Error(\"A\"); })   \u002F\u002F throws → rejects\n    .then(() => console.log(\"B\"))            \u002F\u002F SKIPPED (rejected)\n    .then(() => console.log(\"C\"))            \u002F\u002F SKIPPED\n    .catch(e => { console.log(\"caught:\", e.message); return \"recovered\"; })  \u002F\u002F catches → fulfills with \"recovered\"\n    .then(v => console.log(\"D:\", v));        \u002F\u002F \"D: recovered\" (catch fulfilled the chain)\n\n\u002F\u002F ── A .catch that throws re-rejects (propagates further) ──\nPromise.reject(new Error(\"original\"))\n    .catch(e => { console.log(\"caught:\", e.message); throw new Error(\"re-thrown\"); })\n    .catch(e => console.log(\"caught again:\", e.message));  \u002F\u002F \"caught again: re-thrown\"\n\n\u002F\u002F ── Unhandled rejections (no .catch anywhere) ──\n\u002F\u002F Promise.reject(new Error(\"unhandled\"));\n\u002F\u002F In Node: \"UnhandledPromiseRejection\" warning (or process exit with --unhandled-rejections=strict)\n\u002F\u002F In browser: \"unhandledrejection\" event fires\n\u002F\u002F Always add .catch (or use try\u002Fcatch with async\u002Fawait) to handle errors!\n\n\u002F\u002F ── Recovery with fallback ──\nasync function fetchWithFallback(url, fallbackUrl) {\n    try {\n        return await fetch(url).then(r => r.json());\n    } catch {\n        console.warn(\"primary failed, using fallback\");\n        return await fetch(fallbackUrl).then(r => r.json());\n    }\n}\n\n\u002F\u002F ── Graceful degradation with allSettled ──\nasync function loadWithOptionalEndpoints(critical, optional) {\n    const [criticalResult, optionalResult] = await Promise.allSettled([\n        fetch(critical).then(r => r.json()),\n        fetch(optional).then(r => r.json()),\n    ]);\n    if (criticalResult.status === \"rejected\") throw criticalResult.reason;\n    return {\n        critical: criticalResult.value,\n        optional: optionalResult.status === \"fulfilled\" ? optionalResult.value : null,\n    };\n}\n",[30,2022,2023,2028,2038,2067,2092,2116,2153,2180,2184,2189,2210,2246,2273,2277,2282,2287,2292,2297,2302,2306,2311,2333,2339,2366,2374,2388,2413,2417,2421,2425,2430,2451,2480,2501,2522,2527,2546,2553,2558,2582,2587],{"__ignoreMap":28},[33,2024,2025],{"class":35,"line":36},[33,2026,2027],{"class":39},"\u002F\u002F ── Errors skip .then handlers and propagate to .catch ──\n",[33,2029,2030,2032,2034,2036],{"class":35,"line":43},[33,2031,440],{"class":122},[33,2033,236],{"class":135},[33,2035,140],{"class":179},[33,2037,781],{"class":135},[33,2039,2040,2042,2044,2046,2048,2050,2052,2054,2056,2058,2061,2064],{"class":35,"line":49},[33,2041,457],{"class":135},[33,2043,386],{"class":179},[33,2045,183],{"class":135},[33,2047,152],{"class":118},[33,2049,794],{"class":135},[33,2051,797],{"class":118},[33,2053,129],{"class":118},[33,2055,273],{"class":179},[33,2057,191],{"class":135},[33,2059,2060],{"class":194},"\"A\"",[33,2062,2063],{"class":135},"); })   ",[33,2065,2066],{"class":39},"\u002F\u002F throws → rejects\n",[33,2068,2069,2071,2073,2075,2077,2079,2081,2083,2086,2089],{"class":35,"line":55},[33,2070,457],{"class":135},[33,2072,386],{"class":179},[33,2074,183],{"class":135},[33,2076,152],{"class":118},[33,2078,397],{"class":135},[33,2080,400],{"class":179},[33,2082,191],{"class":135},[33,2084,2085],{"class":194},"\"B\"",[33,2087,2088],{"class":135},"))            ",[33,2090,2091],{"class":39},"\u002F\u002F SKIPPED (rejected)\n",[33,2093,2094,2096,2098,2100,2102,2104,2106,2108,2111,2113],{"class":35,"line":61},[33,2095,457],{"class":135},[33,2097,386],{"class":179},[33,2099,183],{"class":135},[33,2101,152],{"class":118},[33,2103,397],{"class":135},[33,2105,400],{"class":179},[33,2107,191],{"class":135},[33,2109,2110],{"class":194},"\"C\"",[33,2112,2088],{"class":135},[33,2114,2115],{"class":39},"\u002F\u002F SKIPPED\n",[33,2117,2118,2120,2122,2124,2127,2129,2132,2134,2136,2138,2141,2144,2147,2150],{"class":35,"line":67},[33,2119,457],{"class":135},[33,2121,415],{"class":179},[33,2123,191],{"class":135},[33,2125,2126],{"class":139},"e",[33,2128,394],{"class":118},[33,2130,2131],{"class":135}," { console.",[33,2133,400],{"class":179},[33,2135,191],{"class":135},[33,2137,680],{"class":194},[33,2139,2140],{"class":135},", e.message); ",[33,2142,2143],{"class":118},"return",[33,2145,2146],{"class":194}," \"recovered\"",[33,2148,2149],{"class":135},"; })  ",[33,2151,2152],{"class":39},"\u002F\u002F catches → fulfills with \"recovered\"\n",[33,2154,2155,2157,2159,2161,2163,2165,2167,2169,2171,2174,2177],{"class":35,"line":73},[33,2156,457],{"class":135},[33,2158,386],{"class":179},[33,2160,191],{"class":135},[33,2162,391],{"class":139},[33,2164,394],{"class":118},[33,2166,397],{"class":135},[33,2168,400],{"class":179},[33,2170,191],{"class":135},[33,2172,2173],{"class":194},"\"D:\"",[33,2175,2176],{"class":135},", v));        ",[33,2178,2179],{"class":39},"\u002F\u002F \"D: recovered\" (catch fulfilled the chain)\n",[33,2181,2182],{"class":35,"line":79},[33,2183,106],{"emptyLinePlaceholder":105},[33,2185,2186],{"class":35,"line":85},[33,2187,2188],{"class":39},"\u002F\u002F ── A .catch that throws re-rejects (propagates further) ──\n",[33,2190,2191,2193,2195,2197,2199,2201,2203,2205,2208],{"class":35,"line":90},[33,2192,440],{"class":122},[33,2194,236],{"class":135},[33,2196,146],{"class":179},[33,2198,191],{"class":135},[33,2200,270],{"class":118},[33,2202,273],{"class":179},[33,2204,191],{"class":135},[33,2206,2207],{"class":194},"\"original\"",[33,2209,658],{"class":135},[33,2211,2212,2214,2216,2218,2220,2222,2224,2226,2228,2230,2232,2234,2236,2238,2240,2243],{"class":35,"line":96},[33,2213,457],{"class":135},[33,2215,415],{"class":179},[33,2217,191],{"class":135},[33,2219,2126],{"class":139},[33,2221,394],{"class":118},[33,2223,2131],{"class":135},[33,2225,400],{"class":179},[33,2227,191],{"class":135},[33,2229,680],{"class":194},[33,2231,2140],{"class":135},[33,2233,797],{"class":118},[33,2235,129],{"class":118},[33,2237,273],{"class":179},[33,2239,191],{"class":135},[33,2241,2242],{"class":194},"\"re-thrown\"",[33,2244,2245],{"class":135},"); })\n",[33,2247,2248,2250,2252,2254,2256,2258,2260,2262,2264,2267,2270],{"class":35,"line":102},[33,2249,457],{"class":135},[33,2251,415],{"class":179},[33,2253,191],{"class":135},[33,2255,2126],{"class":139},[33,2257,394],{"class":118},[33,2259,397],{"class":135},[33,2261,400],{"class":179},[33,2263,191],{"class":135},[33,2265,2266],{"class":194},"\"caught again:\"",[33,2268,2269],{"class":135},", e.message));  ",[33,2271,2272],{"class":39},"\u002F\u002F \"caught again: re-thrown\"\n",[33,2274,2275],{"class":35,"line":109},[33,2276,106],{"emptyLinePlaceholder":105},[33,2278,2279],{"class":35,"line":115},[33,2280,2281],{"class":39},"\u002F\u002F ── Unhandled rejections (no .catch anywhere) ──\n",[33,2283,2284],{"class":35,"line":158},[33,2285,2286],{"class":39},"\u002F\u002F Promise.reject(new Error(\"unhandled\"));\n",[33,2288,2289],{"class":35,"line":164},[33,2290,2291],{"class":39},"\u002F\u002F In Node: \"UnhandledPromiseRejection\" warning (or process exit with --unhandled-rejections=strict)\n",[33,2293,2294],{"class":35,"line":170},[33,2295,2296],{"class":39},"\u002F\u002F In browser: \"unhandledrejection\" event fires\n",[33,2298,2299],{"class":35,"line":176},[33,2300,2301],{"class":39},"\u002F\u002F Always add .catch (or use try\u002Fcatch with async\u002Fawait) to handle errors!\n",[33,2303,2304],{"class":35,"line":207},[33,2305,106],{"emptyLinePlaceholder":105},[33,2307,2308],{"class":35,"line":213},[33,2309,2310],{"class":39},"\u002F\u002F ── Recovery with fallback ──\n",[33,2312,2313,2315,2317,2320,2322,2325,2327,2330],{"class":35,"line":218},[33,2314,1266],{"class":118},[33,2316,1269],{"class":118},[33,2318,2319],{"class":179}," fetchWithFallback",[33,2321,191],{"class":135},[33,2323,2324],{"class":139},"url",[33,2326,143],{"class":135},[33,2328,2329],{"class":139},"fallbackUrl",[33,2331,2332],{"class":135},") {\n",[33,2334,2335,2337],{"class":35,"line":224},[33,2336,1280],{"class":118},[33,2338,155],{"class":135},[33,2340,2341,2344,2346,2348,2351,2353,2355,2357,2359,2361,2363],{"class":35,"line":252},[33,2342,2343],{"class":118},"        return",[33,2345,1295],{"class":118},[33,2347,564],{"class":179},[33,2349,2350],{"class":135},"(url).",[33,2352,386],{"class":179},[33,2354,191],{"class":135},[33,2356,1486],{"class":139},[33,2358,394],{"class":118},[33,2360,1491],{"class":135},[33,2362,599],{"class":179},[33,2364,2365],{"class":135},"());\n",[33,2367,2368,2370,2372],{"class":35,"line":287},[33,2369,1375],{"class":135},[33,2371,415],{"class":118},[33,2373,155],{"class":135},[33,2375,2376,2378,2381,2383,2386],{"class":35,"line":292},[33,2377,1366],{"class":135},[33,2379,2380],{"class":179},"warn",[33,2382,191],{"class":135},[33,2384,2385],{"class":194},"\"primary failed, using fallback\"",[33,2387,204],{"class":135},[33,2389,2390,2392,2394,2396,2399,2401,2403,2405,2407,2409,2411],{"class":35,"line":298},[33,2391,2343],{"class":118},[33,2393,1295],{"class":118},[33,2395,564],{"class":179},[33,2397,2398],{"class":135},"(fallbackUrl).",[33,2400,386],{"class":179},[33,2402,191],{"class":135},[33,2404,1486],{"class":139},[33,2406,394],{"class":118},[33,2408,1491],{"class":135},[33,2410,599],{"class":179},[33,2412,2365],{"class":135},[33,2414,2415],{"class":35,"line":326},[33,2416,1398],{"class":135},[33,2418,2419],{"class":35,"line":342},[33,2420,1403],{"class":135},[33,2422,2423],{"class":35,"line":358},[33,2424,106],{"emptyLinePlaceholder":105},[33,2426,2427],{"class":35,"line":375},[33,2428,2429],{"class":39},"\u002F\u002F ── Graceful degradation with allSettled ──\n",[33,2431,2432,2434,2436,2439,2441,2444,2446,2449],{"class":35,"line":380},[33,2433,1266],{"class":118},[33,2435,1269],{"class":118},[33,2437,2438],{"class":179}," loadWithOptionalEndpoints",[33,2440,191],{"class":135},[33,2442,2443],{"class":139},"critical",[33,2445,143],{"class":135},[33,2447,2448],{"class":139},"optional",[33,2450,2332],{"class":135},[33,2452,2453,2456,2458,2461,2463,2466,2468,2470,2472,2474,2476,2478],{"class":35,"line":914},[33,2454,2455],{"class":118},"    const",[33,2457,1443],{"class":135},[33,2459,2460],{"class":122},"criticalResult",[33,2462,143],{"class":135},[33,2464,2465],{"class":122},"optionalResult",[33,2467,1452],{"class":135},[33,2469,1455],{"class":118},[33,2471,1295],{"class":118},[33,2473,132],{"class":122},[33,2475,236],{"class":135},[33,2477,1416],{"class":179},[33,2479,1466],{"class":135},[33,2481,2482,2484,2487,2489,2491,2493,2495,2497,2499],{"class":35,"line":924},[33,2483,1024],{"class":179},[33,2485,2486],{"class":135},"(critical).",[33,2488,386],{"class":179},[33,2490,191],{"class":135},[33,2492,1486],{"class":139},[33,2494,394],{"class":118},[33,2496,1491],{"class":135},[33,2498,599],{"class":179},[33,2500,1496],{"class":135},[33,2502,2503,2505,2508,2510,2512,2514,2516,2518,2520],{"class":35,"line":944},[33,2504,1024],{"class":179},[33,2506,2507],{"class":135},"(optional).",[33,2509,386],{"class":179},[33,2511,191],{"class":135},[33,2513,1486],{"class":139},[33,2515,394],{"class":118},[33,2517,1491],{"class":135},[33,2519,599],{"class":179},[33,2521,1496],{"class":135},[33,2523,2524],{"class":35,"line":967},[33,2525,2526],{"class":135},"    ]);\n",[33,2528,2529,2531,2534,2536,2539,2541,2543],{"class":35,"line":973},[33,2530,1797],{"class":118},[33,2532,2533],{"class":135}," (criticalResult.status ",[33,2535,1803],{"class":118},[33,2537,2538],{"class":194}," \"rejected\"",[33,2540,149],{"class":135},[33,2542,797],{"class":118},[33,2544,2545],{"class":135}," criticalResult.reason;\n",[33,2547,2548,2551],{"class":35,"line":1927},[33,2549,2550],{"class":118},"    return",[33,2552,155],{"class":135},[33,2554,2555],{"class":35,"line":1956},[33,2556,2557],{"class":135},"        critical: criticalResult.value,\n",[33,2559,2560,2563,2565,2567,2570,2573,2576,2579],{"class":35,"line":1961},[33,2561,2562],{"class":135},"        optional: optionalResult.status ",[33,2564,1803],{"class":118},[33,2566,1806],{"class":194},[33,2568,2569],{"class":118}," ?",[33,2571,2572],{"class":135}," optionalResult.value ",[33,2574,2575],{"class":118},":",[33,2577,2578],{"class":122}," null",[33,2580,2581],{"class":135},",\n",[33,2583,2584],{"class":35,"line":1967},[33,2585,2586],{"class":135},"    };\n",[33,2588,2589],{"class":35,"line":1972},[33,2590,1403],{"class":135},[15,2592,2594],{"id":2593},"production-pattern-concurrent-fetch-with-rate-limiting","Production Pattern: Concurrent Fetch with Rate Limiting",[20,2596,2597],{"language":22},[24,2598,2600],{"className":26,"code":2599,"language":22,"meta":28,"style":28},"\u002F\u002F ── Limit concurrent Promises (avoid overwhelming the server) ──\nasync function mapLimit(items, limit, asyncFn) {\n    const results = [];\n    let index = 0;\n\n    async function worker() {\n        while (index \u003C items.length) {\n            const i = index++;  \u002F\u002F claim the next item (atomic increment)\n            results[i] = await asyncFn(items[i], i);  \u002F\u002F preserve order\n        }\n    }\n\n    \u002F\u002F Start `limit` workers (each processes items until exhausted)\n    await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));\n    return results;\n}\n\n\u002F\u002F Usage: fetch 100 URLs with max 5 concurrent\nconst urls = Array.from({ length: 100 }, (_, i) => `https:\u002F\u002Fapi.example.com\u002F${i}`);\nconst responses = await mapLimit(urls, 5, url =>\n    fetch(url).then(r => r.json())\n);\n\n\u002F\u002F ── Batch with retry and timeout ──\nasync function fetchWithRetry(url, { retries = 3, timeout = 5000 } = {}) {\n    for (let attempt = 0; attempt \u003C retries; attempt++) {\n        try {\n            const controller = new AbortController();\n            const timer = setTimeout(() => controller.abort(), timeout);\n            const response = await fetch(url, { signal: controller.signal });\n            clearTimeout(timer);\n            if (!response.ok) throw new Error(`HTTP ${response.status}`);\n            return await response.json();\n        } catch (err) {\n            if (attempt === retries - 1) throw err;\n            await new Promise(r => setTimeout(r, 1000 * 2 ** attempt));  \u002F\u002F exponential backoff\n        }\n    }\n}\n",[30,2601,2602,2607,2633,2644,2660,2664,2676,2695,2717,2735,2740,2744,2748,2753,2784,2791,2795,2799,2804,2847,2873,2894,2898,2902,2907,2948,2977,2984,3001,3025,3041,3049,3084,3097,3106,3130,3167,3171,3175],{"__ignoreMap":28},[33,2603,2604],{"class":35,"line":36},[33,2605,2606],{"class":39},"\u002F\u002F ── Limit concurrent Promises (avoid overwhelming the server) ──\n",[33,2608,2609,2611,2613,2616,2618,2621,2623,2626,2628,2631],{"class":35,"line":43},[33,2610,1266],{"class":118},[33,2612,1269],{"class":118},[33,2614,2615],{"class":179}," mapLimit",[33,2617,191],{"class":135},[33,2619,2620],{"class":139},"items",[33,2622,143],{"class":135},[33,2624,2625],{"class":139},"limit",[33,2627,143],{"class":135},[33,2629,2630],{"class":139},"asyncFn",[33,2632,2332],{"class":135},[33,2634,2635,2637,2639,2641],{"class":35,"line":49},[33,2636,2455],{"class":118},[33,2638,1657],{"class":122},[33,2640,126],{"class":118},[33,2642,2643],{"class":135}," [];\n",[33,2645,2646,2649,2652,2654,2657],{"class":35,"line":55},[33,2647,2648],{"class":118},"    let",[33,2650,2651],{"class":135}," index ",[33,2653,1455],{"class":118},[33,2655,2656],{"class":122}," 0",[33,2658,2659],{"class":135},";\n",[33,2661,2662],{"class":35,"line":61},[33,2663,106],{"emptyLinePlaceholder":105},[33,2665,2666,2669,2671,2674],{"class":35,"line":67},[33,2667,2668],{"class":118},"    async",[33,2670,1269],{"class":118},[33,2672,2673],{"class":179}," worker",[33,2675,1275],{"class":135},[33,2677,2678,2681,2684,2687,2690,2693],{"class":35,"line":73},[33,2679,2680],{"class":118},"        while",[33,2682,2683],{"class":135}," (index ",[33,2685,2686],{"class":118},"\u003C",[33,2688,2689],{"class":135}," items.",[33,2691,2692],{"class":122},"length",[33,2694,2332],{"class":135},[33,2696,2697,2700,2703,2705,2708,2711,2714],{"class":35,"line":79},[33,2698,2699],{"class":118},"            const",[33,2701,2702],{"class":122}," i",[33,2704,126],{"class":118},[33,2706,2707],{"class":135}," index",[33,2709,2710],{"class":118},"++",[33,2712,2713],{"class":135},";  ",[33,2715,2716],{"class":39},"\u002F\u002F claim the next item (atomic increment)\n",[33,2718,2719,2722,2724,2726,2729,2732],{"class":35,"line":85},[33,2720,2721],{"class":135},"            results[i] ",[33,2723,1455],{"class":118},[33,2725,1295],{"class":118},[33,2727,2728],{"class":179}," asyncFn",[33,2730,2731],{"class":135},"(items[i], i);  ",[33,2733,2734],{"class":39},"\u002F\u002F preserve order\n",[33,2736,2737],{"class":35,"line":90},[33,2738,2739],{"class":135},"        }\n",[33,2741,2742],{"class":35,"line":96},[33,2743,1398],{"class":135},[33,2745,2746],{"class":35,"line":102},[33,2747,106],{"emptyLinePlaceholder":105},[33,2749,2750],{"class":35,"line":109},[33,2751,2752],{"class":39},"    \u002F\u002F Start `limit` workers (each processes items until exhausted)\n",[33,2754,2755,2758,2760,2762,2764,2767,2770,2773,2776,2779,2781],{"class":35,"line":115},[33,2756,2757],{"class":118},"    await",[33,2759,132],{"class":122},[33,2761,236],{"class":135},[33,2763,1410],{"class":179},[33,2765,2766],{"class":135},"(Array.",[33,2768,2769],{"class":179},"from",[33,2771,2772],{"class":135},"({ length: Math.",[33,2774,2775],{"class":179},"min",[33,2777,2778],{"class":135},"(limit, items.",[33,2780,2692],{"class":122},[33,2782,2783],{"class":135},") }, worker));\n",[33,2785,2786,2788],{"class":35,"line":158},[33,2787,2550],{"class":118},[33,2789,2790],{"class":135}," results;\n",[33,2792,2793],{"class":35,"line":164},[33,2794,1403],{"class":135},[33,2796,2797],{"class":35,"line":170},[33,2798,106],{"emptyLinePlaceholder":105},[33,2800,2801],{"class":35,"line":176},[33,2802,2803],{"class":39},"\u002F\u002F Usage: fetch 100 URLs with max 5 concurrent\n",[33,2805,2806,2808,2811,2813,2816,2818,2821,2824,2827,2829,2831,2834,2836,2838,2841,2843,2845],{"class":35,"line":207},[33,2807,119],{"class":118},[33,2809,2810],{"class":122}," urls",[33,2812,126],{"class":118},[33,2814,2815],{"class":135}," Array.",[33,2817,2769],{"class":179},[33,2819,2820],{"class":135},"({ length: ",[33,2822,2823],{"class":122},"100",[33,2825,2826],{"class":135}," }, (",[33,2828,1594],{"class":139},[33,2830,143],{"class":135},[33,2832,2833],{"class":139},"i",[33,2835,149],{"class":135},[33,2837,152],{"class":118},[33,2839,2840],{"class":194}," `https:\u002F\u002Fapi.example.com\u002F${",[33,2842,2833],{"class":135},[33,2844,574],{"class":194},[33,2846,204],{"class":135},[33,2848,2849,2851,2854,2856,2858,2860,2863,2866,2868,2870],{"class":35,"line":213},[33,2850,119],{"class":118},[33,2852,2853],{"class":122}," responses",[33,2855,126],{"class":118},[33,2857,1295],{"class":118},[33,2859,2615],{"class":179},[33,2861,2862],{"class":135},"(urls, ",[33,2864,2865],{"class":122},"5",[33,2867,143],{"class":135},[33,2869,2324],{"class":139},[33,2871,2872],{"class":118}," =>\n",[33,2874,2875,2877,2879,2881,2883,2885,2887,2889,2891],{"class":35,"line":218},[33,2876,1471],{"class":179},[33,2878,2350],{"class":135},[33,2880,386],{"class":179},[33,2882,191],{"class":135},[33,2884,1486],{"class":139},[33,2886,394],{"class":118},[33,2888,1491],{"class":135},[33,2890,599],{"class":179},[33,2892,2893],{"class":135},"())\n",[33,2895,2896],{"class":35,"line":224},[33,2897,204],{"class":135},[33,2899,2900],{"class":35,"line":252},[33,2901,106],{"emptyLinePlaceholder":105},[33,2903,2904],{"class":35,"line":287},[33,2905,2906],{"class":39},"\u002F\u002F ── Batch with retry and timeout ──\n",[33,2908,2909,2911,2913,2916,2918,2920,2923,2926,2928,2930,2932,2935,2937,2940,2943,2945],{"class":35,"line":292},[33,2910,1266],{"class":118},[33,2912,1269],{"class":118},[33,2914,2915],{"class":179}," fetchWithRetry",[33,2917,191],{"class":135},[33,2919,2324],{"class":139},[33,2921,2922],{"class":135},", { ",[33,2924,2925],{"class":139},"retries",[33,2927,126],{"class":118},[33,2929,500],{"class":122},[33,2931,143],{"class":135},[33,2933,2934],{"class":139},"timeout",[33,2936,126],{"class":118},[33,2938,2939],{"class":122}," 5000",[33,2941,2942],{"class":135}," } ",[33,2944,1455],{"class":118},[33,2946,2947],{"class":135}," {}) {\n",[33,2949,2950,2953,2955,2958,2961,2963,2965,2968,2970,2973,2975],{"class":35,"line":298},[33,2951,2952],{"class":118},"    for",[33,2954,1781],{"class":135},[33,2956,2957],{"class":118},"let",[33,2959,2960],{"class":135}," attempt ",[33,2962,1455],{"class":118},[33,2964,2656],{"class":122},[33,2966,2967],{"class":135},"; attempt ",[33,2969,2686],{"class":118},[33,2971,2972],{"class":135}," retries; attempt",[33,2974,2710],{"class":118},[33,2976,2332],{"class":135},[33,2978,2979,2982],{"class":35,"line":326},[33,2980,2981],{"class":118},"        try",[33,2983,155],{"class":135},[33,2985,2986,2988,2991,2993,2995,2998],{"class":35,"line":342},[33,2987,2699],{"class":118},[33,2989,2990],{"class":122}," controller",[33,2992,126],{"class":118},[33,2994,129],{"class":118},[33,2996,2997],{"class":179}," AbortController",[33,2999,3000],{"class":135},"();\n",[33,3002,3003,3005,3008,3010,3012,3014,3016,3019,3022],{"class":35,"line":358},[33,3004,2699],{"class":118},[33,3006,3007],{"class":122}," timer",[33,3009,126],{"class":118},[33,3011,1605],{"class":179},[33,3013,183],{"class":135},[33,3015,152],{"class":118},[33,3017,3018],{"class":135}," controller.",[33,3020,3021],{"class":179},"abort",[33,3023,3024],{"class":135},"(), timeout);\n",[33,3026,3027,3029,3032,3034,3036,3038],{"class":35,"line":375},[33,3028,2699],{"class":118},[33,3030,3031],{"class":122}," response",[33,3033,126],{"class":118},[33,3035,1295],{"class":118},[33,3037,564],{"class":179},[33,3039,3040],{"class":135},"(url, { signal: controller.signal });\n",[33,3042,3043,3046],{"class":35,"line":380},[33,3044,3045],{"class":179},"            clearTimeout",[33,3047,3048],{"class":135},"(timer);\n",[33,3050,3051,3054,3056,3059,3062,3064,3066,3068,3070,3073,3075,3077,3080,3082],{"class":35,"line":914},[33,3052,3053],{"class":118},"            if",[33,3055,1781],{"class":135},[33,3057,3058],{"class":118},"!",[33,3060,3061],{"class":135},"response.ok) ",[33,3063,797],{"class":118},[33,3065,129],{"class":118},[33,3067,273],{"class":179},[33,3069,191],{"class":135},[33,3071,3072],{"class":194},"`HTTP ${",[33,3074,591],{"class":135},[33,3076,236],{"class":194},[33,3078,3079],{"class":135},"status",[33,3081,574],{"class":194},[33,3083,204],{"class":135},[33,3085,3086,3089,3091,3093,3095],{"class":35,"line":924},[33,3087,3088],{"class":118},"            return",[33,3090,1295],{"class":118},[33,3092,596],{"class":135},[33,3094,599],{"class":179},[33,3096,3000],{"class":135},[33,3098,3099,3102,3104],{"class":35,"line":944},[33,3100,3101],{"class":135},"        } ",[33,3103,415],{"class":118},[33,3105,1380],{"class":135},[33,3107,3108,3110,3113,3115,3118,3121,3123,3125,3127],{"class":35,"line":967},[33,3109,3053],{"class":118},[33,3111,3112],{"class":135}," (attempt ",[33,3114,1803],{"class":118},[33,3116,3117],{"class":135}," retries ",[33,3119,3120],{"class":118},"-",[33,3122,474],{"class":122},[33,3124,149],{"class":135},[33,3126,797],{"class":118},[33,3128,3129],{"class":135}," err;\n",[33,3131,3132,3135,3137,3139,3141,3143,3145,3147,3150,3152,3155,3158,3161,3164],{"class":35,"line":973},[33,3133,3134],{"class":118},"            await",[33,3136,129],{"class":118},[33,3138,132],{"class":122},[33,3140,191],{"class":135},[33,3142,1486],{"class":139},[33,3144,394],{"class":118},[33,3146,1605],{"class":179},[33,3148,3149],{"class":135},"(r, ",[33,3151,201],{"class":122},[33,3153,3154],{"class":118}," *",[33,3156,3157],{"class":122}," 2",[33,3159,3160],{"class":118}," **",[33,3162,3163],{"class":135}," attempt));  ",[33,3165,3166],{"class":39},"\u002F\u002F exponential backoff\n",[33,3168,3169],{"class":35,"line":1927},[33,3170,2739],{"class":135},[33,3172,3173],{"class":35,"line":1956},[33,3174,1398],{"class":135},[33,3176,3177],{"class":35,"line":1961},[33,3178,1403],{"class":135},[15,3180,3182],{"id":3181},"tips-tricks","💡 Tips & Tricks",[20,3184,3185],{"language":22},[24,3186,3188],{"className":26,"code":3187,"language":22,"meta":28,"style":28},"\u002F\u002F ── Promise.all for parallel execution (vs sequential await) ──\n\u002F\u002F ❌ SLOW — sequential (each waits for the previous):\nconst a = await fetch(\"\u002Fapi\u002Fa\");\nconst b = await fetch(\"\u002Fapi\u002Fb\");\nconst c = await fetch(\"\u002Fapi\u002Fc\");\n\u002F\u002F Total time: a + b + c (sum of all response times)\n\n\u002F\u002F ✅ FAST — parallel (all start at once):\nconst [a2, b2, c2] = await Promise.all([\n    fetch(\"\u002Fapi\u002Fa\"),\n    fetch(\"\u002Fapi\u002Fb\"),\n    fetch(\"\u002Fapi\u002Fc\"),\n]);\n\u002F\u002F Total time: max(a, b, c) (the slowest one)\n\n\u002F\u002F ── `Promise.resolve` to wrap a non-Promise value ──\nconst p = Promise.resolve(42);  \u002F\u002F fulfilled with 42\n\u002F\u002F .then unwraps: p.then(v => console.log(v))  \u002F\u002F 42\n\n\u002F\u002F ── `Promise.allSettled` for \"try all, collect results\" ──\nconst results = await Promise.allSettled(urls.map(url => fetch(url).then(r => r.json())));\nconst successes = results.filter(r => r.status === \"fulfilled\").map(r => r.value);\nconst failures = results.filter(r => r.status === \"rejected\").map(r => r.reason);\n\n\u002F\u002F ── `Promise.race` for timeout ──\nfunction withTimeout(promise, ms) {\n    return Promise.race([\n        promise,\n        new Promise((_, reject) => setTimeout(() => reject(new Error(\"timeout\")), ms)),\n    ]);\n}\nconst data = await withTimeout(fetch(url), 5000);  \u002F\u002F rejects after 5s if fetch hasn't completed\n\n\u002F\u002F ── Defer a Promise resolve (manual control) ──\nlet resolveLater;\nconst deferred = new Promise(resolve => { resolveLater = resolve; });\n\u002F\u002F resolveLater(42);  \u002F\u002F resolve later (manual control over when the Promise settles)\n",[30,3189,3190,3195,3200,3219,3238,3258,3263,3267,3272,3305,3315,3325,3335,3339,3344,3348,3353,3376,3384,3388,3393,3440,3481,3519,3523,3528,3548,3560,3565,3605,3609,3613,3640,3644,3649,3656,3683],{"__ignoreMap":28},[33,3191,3192],{"class":35,"line":36},[33,3193,3194],{"class":39},"\u002F\u002F ── Promise.all for parallel execution (vs sequential await) ──\n",[33,3196,3197],{"class":35,"line":43},[33,3198,3199],{"class":39},"\u002F\u002F ❌ SLOW — sequential (each waits for the previous):\n",[33,3201,3202,3204,3207,3209,3211,3213,3215,3217],{"class":35,"line":49},[33,3203,119],{"class":118},[33,3205,3206],{"class":122}," a",[33,3208,126],{"class":118},[33,3210,1295],{"class":118},[33,3212,564],{"class":179},[33,3214,191],{"class":135},[33,3216,1678],{"class":194},[33,3218,204],{"class":135},[33,3220,3221,3223,3226,3228,3230,3232,3234,3236],{"class":35,"line":55},[33,3222,119],{"class":118},[33,3224,3225],{"class":122}," b",[33,3227,126],{"class":118},[33,3229,1295],{"class":118},[33,3231,564],{"class":179},[33,3233,191],{"class":135},[33,3235,1703],{"class":194},[33,3237,204],{"class":135},[33,3239,3240,3242,3245,3247,3249,3251,3253,3256],{"class":35,"line":61},[33,3241,119],{"class":118},[33,3243,3244],{"class":122}," c",[33,3246,126],{"class":118},[33,3248,1295],{"class":118},[33,3250,564],{"class":179},[33,3252,191],{"class":135},[33,3254,3255],{"class":194},"\"\u002Fapi\u002Fc\"",[33,3257,204],{"class":135},[33,3259,3260],{"class":35,"line":67},[33,3261,3262],{"class":39},"\u002F\u002F Total time: a + b + c (sum of all response times)\n",[33,3264,3265],{"class":35,"line":73},[33,3266,106],{"emptyLinePlaceholder":105},[33,3268,3269],{"class":35,"line":79},[33,3270,3271],{"class":39},"\u002F\u002F ✅ FAST — parallel (all start at once):\n",[33,3273,3274,3276,3278,3281,3283,3286,3288,3291,3293,3295,3297,3299,3301,3303],{"class":35,"line":85},[33,3275,119],{"class":118},[33,3277,1443],{"class":135},[33,3279,3280],{"class":122},"a2",[33,3282,143],{"class":135},[33,3284,3285],{"class":122},"b2",[33,3287,143],{"class":135},[33,3289,3290],{"class":122},"c2",[33,3292,1452],{"class":135},[33,3294,1455],{"class":118},[33,3296,1295],{"class":118},[33,3298,132],{"class":122},[33,3300,236],{"class":135},[33,3302,1410],{"class":179},[33,3304,1466],{"class":135},[33,3306,3307,3309,3311,3313],{"class":35,"line":90},[33,3308,1471],{"class":179},[33,3310,191],{"class":135},[33,3312,1678],{"class":194},[33,3314,1571],{"class":135},[33,3316,3317,3319,3321,3323],{"class":35,"line":96},[33,3318,1471],{"class":179},[33,3320,191],{"class":135},[33,3322,1703],{"class":194},[33,3324,1571],{"class":135},[33,3326,3327,3329,3331,3333],{"class":35,"line":102},[33,3328,1471],{"class":179},[33,3330,191],{"class":135},[33,3332,3255],{"class":194},[33,3334,1571],{"class":135},[33,3336,3337],{"class":35,"line":109},[33,3338,1526],{"class":135},[33,3340,3341],{"class":35,"line":115},[33,3342,3343],{"class":39},"\u002F\u002F Total time: max(a, b, c) (the slowest one)\n",[33,3345,3346],{"class":35,"line":158},[33,3347,106],{"emptyLinePlaceholder":105},[33,3349,3350],{"class":35,"line":164},[33,3351,3352],{"class":39},"\u002F\u002F ── `Promise.resolve` to wrap a non-Promise value ──\n",[33,3354,3355,3357,3359,3361,3363,3365,3367,3369,3371,3373],{"class":35,"line":170},[33,3356,119],{"class":118},[33,3358,303],{"class":122},[33,3360,126],{"class":118},[33,3362,132],{"class":122},[33,3364,236],{"class":135},[33,3366,140],{"class":179},[33,3368,191],{"class":135},[33,3370,243],{"class":122},[33,3372,246],{"class":135},[33,3374,3375],{"class":39},"\u002F\u002F fulfilled with 42\n",[33,3377,3378,3381],{"class":35,"line":176},[33,3379,3380],{"class":39},"\u002F\u002F .then unwraps: p.then(v => console.log(v))",[33,3382,3383],{"class":39},"  \u002F\u002F 42\n",[33,3385,3386],{"class":35,"line":207},[33,3387,106],{"emptyLinePlaceholder":105},[33,3389,3390],{"class":35,"line":213},[33,3391,3392],{"class":39},"\u002F\u002F ── `Promise.allSettled` for \"try all, collect results\" ──\n",[33,3394,3395,3397,3399,3401,3403,3405,3407,3409,3412,3415,3417,3419,3421,3423,3425,3427,3429,3431,3433,3435,3437],{"class":35,"line":218},[33,3396,119],{"class":118},[33,3398,1657],{"class":122},[33,3400,126],{"class":118},[33,3402,1295],{"class":118},[33,3404,132],{"class":122},[33,3406,236],{"class":135},[33,3408,1416],{"class":179},[33,3410,3411],{"class":135},"(urls.",[33,3413,3414],{"class":179},"map",[33,3416,191],{"class":135},[33,3418,2324],{"class":139},[33,3420,394],{"class":118},[33,3422,564],{"class":179},[33,3424,2350],{"class":135},[33,3426,386],{"class":179},[33,3428,191],{"class":135},[33,3430,1486],{"class":139},[33,3432,394],{"class":118},[33,3434,1491],{"class":135},[33,3436,599],{"class":179},[33,3438,3439],{"class":135},"())));\n",[33,3441,3442,3444,3447,3449,3452,3455,3457,3459,3461,3464,3466,3468,3470,3472,3474,3476,3478],{"class":35,"line":224},[33,3443,119],{"class":118},[33,3445,3446],{"class":122}," successes",[33,3448,126],{"class":118},[33,3450,3451],{"class":135}," results.",[33,3453,3454],{"class":179},"filter",[33,3456,191],{"class":135},[33,3458,1486],{"class":139},[33,3460,394],{"class":118},[33,3462,3463],{"class":135}," r.status ",[33,3465,1803],{"class":118},[33,3467,1806],{"class":194},[33,3469,1479],{"class":135},[33,3471,3414],{"class":179},[33,3473,191],{"class":135},[33,3475,1486],{"class":139},[33,3477,394],{"class":118},[33,3479,3480],{"class":135}," r.value);\n",[33,3482,3483,3485,3488,3490,3492,3494,3496,3498,3500,3502,3504,3506,3508,3510,3512,3514,3516],{"class":35,"line":252},[33,3484,119],{"class":118},[33,3486,3487],{"class":122}," failures",[33,3489,126],{"class":118},[33,3491,3451],{"class":135},[33,3493,3454],{"class":179},[33,3495,191],{"class":135},[33,3497,1486],{"class":139},[33,3499,394],{"class":118},[33,3501,3463],{"class":135},[33,3503,1803],{"class":118},[33,3505,2538],{"class":194},[33,3507,1479],{"class":135},[33,3509,3414],{"class":179},[33,3511,191],{"class":135},[33,3513,1486],{"class":139},[33,3515,394],{"class":118},[33,3517,3518],{"class":135}," r.reason);\n",[33,3520,3521],{"class":35,"line":287},[33,3522,106],{"emptyLinePlaceholder":105},[33,3524,3525],{"class":35,"line":292},[33,3526,3527],{"class":39},"\u002F\u002F ── `Promise.race` for timeout ──\n",[33,3529,3530,3533,3536,3538,3541,3543,3546],{"class":35,"line":298},[33,3531,3532],{"class":118},"function",[33,3534,3535],{"class":179}," withTimeout",[33,3537,191],{"class":135},[33,3539,3540],{"class":139},"promise",[33,3542,143],{"class":135},[33,3544,3545],{"class":139},"ms",[33,3547,2332],{"class":135},[33,3549,3550,3552,3554,3556,3558],{"class":35,"line":326},[33,3551,2550],{"class":118},[33,3553,132],{"class":122},[33,3555,236],{"class":135},[33,3557,1413],{"class":179},[33,3559,1466],{"class":135},[33,3561,3562],{"class":35,"line":342},[33,3563,3564],{"class":135},"        promise,\n",[33,3566,3567,3570,3572,3574,3576,3578,3580,3582,3584,3586,3588,3590,3592,3594,3596,3598,3600,3602],{"class":35,"line":358},[33,3568,3569],{"class":118},"        new",[33,3571,132],{"class":122},[33,3573,136],{"class":135},[33,3575,1594],{"class":139},[33,3577,143],{"class":135},[33,3579,146],{"class":139},[33,3581,149],{"class":135},[33,3583,152],{"class":118},[33,3585,1605],{"class":179},[33,3587,183],{"class":135},[33,3589,152],{"class":118},[33,3591,1612],{"class":179},[33,3593,191],{"class":135},[33,3595,270],{"class":118},[33,3597,273],{"class":179},[33,3599,191],{"class":135},[33,3601,1623],{"class":194},[33,3603,3604],{"class":135},")), ms)),\n",[33,3606,3607],{"class":35,"line":375},[33,3608,2526],{"class":135},[33,3610,3611],{"class":35,"line":380},[33,3612,1403],{"class":135},[33,3614,3615,3617,3620,3622,3624,3626,3628,3630,3633,3635,3637],{"class":35,"line":914},[33,3616,119],{"class":118},[33,3618,3619],{"class":122}," data",[33,3621,126],{"class":118},[33,3623,1295],{"class":118},[33,3625,3535],{"class":179},[33,3627,191],{"class":135},[33,3629,997],{"class":179},[33,3631,3632],{"class":135},"(url), ",[33,3634,1629],{"class":122},[33,3636,246],{"class":135},[33,3638,3639],{"class":39},"\u002F\u002F rejects after 5s if fetch hasn't completed\n",[33,3641,3642],{"class":35,"line":924},[33,3643,106],{"emptyLinePlaceholder":105},[33,3645,3646],{"class":35,"line":944},[33,3647,3648],{"class":39},"\u002F\u002F ── Defer a Promise resolve (manual control) ──\n",[33,3650,3651,3653],{"class":35,"line":967},[33,3652,2957],{"class":118},[33,3654,3655],{"class":135}," resolveLater;\n",[33,3657,3658,3660,3663,3665,3667,3669,3671,3673,3675,3678,3680],{"class":35,"line":973},[33,3659,119],{"class":118},[33,3661,3662],{"class":122}," deferred",[33,3664,126],{"class":118},[33,3666,129],{"class":118},[33,3668,132],{"class":122},[33,3670,191],{"class":135},[33,3672,140],{"class":139},[33,3674,394],{"class":118},[33,3676,3677],{"class":135}," { resolveLater ",[33,3679,1455],{"class":118},[33,3681,3682],{"class":135}," resolve; });\n",[33,3684,3685,3688],{"class":35,"line":1927},[33,3686,3687],{"class":39},"\u002F\u002F resolveLater(42);",[33,3689,3690],{"class":39},"  \u002F\u002F resolve later (manual control over when the Promise settles)\n",[15,3692,3694],{"id":3693},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[20,3696,3697],{"language":22},[24,3698,3700],{"className":26,"code":3699,"language":22,"meta":28,"style":28},"\u002F\u002F ── Unhandled rejections crash silently (or crash the process) ──\n\u002F\u002F Promise.reject(new Error(\"oops\"));  \u002F\u002F no .catch → UnhandledPromiseRejection\n\u002F\u002F Always add .catch or use async\u002Fawait with try\u002Fcatch.\n\n\u002F\u002F ── .then(onFulfilled, onRejected) — errors in onFulfilled are NOT caught by onRejected ──\nPromise.resolve()\n    .then(\n        () => { throw new Error(\"in onFulfilled\"); },\n        (e) => console.log(\"in onRejected:\", e)  \u002F\u002F NOT called! (this catches rejections from the PREVIOUS Promise, not errors in onFulfilled)\n    )\n    .catch(e => console.log(\"caught:\", e.message));  \u002F\u002F \"caught: in onFulfilled\" (caught here, not in onRejected)\n\n\u002F\u002F ── .finally doesn't receive the value (and doesn't change it) ──\nPromise.resolve(\"data\")\n    .finally(() => console.log(\"finally\"))  \u002F\u002F no argument — finally doesn't get the value\n    .then(v => console.log(v));  \u002F\u002F \"data\" (finally didn't change the value)\n\u002F\u002F If finally returns a value or throws, it DOES affect the chain:\nPromise.resolve(\"data\")\n    .finally(() => \"overridden\")  \u002F\u002F returns a value → but the original value is preserved (finally ignores return)\n    .then(v => console.log(v));  \u002F\u002F \"data\" (finally's return is ignored for non-throwing)\n\n\u002F\u002F ── Promise.all rejects on FIRST rejection (others keep running) ──\n\u002F\u002F Promise.all doesn't cancel the other Promises — they keep running (just ignored).\n\u002F\u002F Use AbortController to actually cancel ongoing fetches.\n\n\u002F\u002F ── Returning a non-Promise from .then wraps it in Promise.resolve ──\nPromise.resolve(1)\n    .then(v => v + 1)  \u002F\u002F returns 2 (a number) → Promise.resolve(2) → next .then gets 2\n    .then(v => { console.log(v) });  \u002F\u002F 2\n\n\u002F\u002F ── Throwing in a .then rejects the returned Promise ──\nPromise.resolve()\n    .then(() => { throw new Error(\"boom\"); })  \u002F\u002F returns a rejected Promise\n    .catch(e => console.log(e.message));  \u002F\u002F \"boom\"\n",[30,3701,3702,3707,3715,3720,3724,3729,3739,3747,3770,3795,3800,3825,3829,3834,3848,3872,3893,3898,3912,3931,3952,3956,3961,3966,3971,3975,3980,3994,4017,4039,4043,4048,4058,4085],{"__ignoreMap":28},[33,3703,3704],{"class":35,"line":36},[33,3705,3706],{"class":39},"\u002F\u002F ── Unhandled rejections crash silently (or crash the process) ──\n",[33,3708,3709,3712],{"class":35,"line":43},[33,3710,3711],{"class":39},"\u002F\u002F Promise.reject(new Error(\"oops\"));",[33,3713,3714],{"class":39},"  \u002F\u002F no .catch → UnhandledPromiseRejection\n",[33,3716,3717],{"class":35,"line":49},[33,3718,3719],{"class":39},"\u002F\u002F Always add .catch or use async\u002Fawait with try\u002Fcatch.\n",[33,3721,3722],{"class":35,"line":55},[33,3723,106],{"emptyLinePlaceholder":105},[33,3725,3726],{"class":35,"line":61},[33,3727,3728],{"class":39},"\u002F\u002F ── .then(onFulfilled, onRejected) — errors in onFulfilled are NOT caught by onRejected ──\n",[33,3730,3731,3733,3735,3737],{"class":35,"line":67},[33,3732,440],{"class":122},[33,3734,236],{"class":135},[33,3736,140],{"class":179},[33,3738,781],{"class":135},[33,3740,3741,3743,3745],{"class":35,"line":73},[33,3742,457],{"class":135},[33,3744,386],{"class":179},[33,3746,921],{"class":135},[33,3748,3749,3752,3754,3756,3758,3760,3762,3764,3767],{"class":35,"line":79},[33,3750,3751],{"class":135},"        () ",[33,3753,152],{"class":118},[33,3755,794],{"class":135},[33,3757,797],{"class":118},[33,3759,129],{"class":118},[33,3761,273],{"class":179},[33,3763,191],{"class":135},[33,3765,3766],{"class":194},"\"in onFulfilled\"",[33,3768,3769],{"class":135},"); },\n",[33,3771,3772,3775,3777,3779,3781,3783,3785,3787,3790,3792],{"class":35,"line":85},[33,3773,3774],{"class":135},"        (",[33,3776,2126],{"class":139},[33,3778,149],{"class":135},[33,3780,152],{"class":118},[33,3782,397],{"class":135},[33,3784,400],{"class":179},[33,3786,191],{"class":135},[33,3788,3789],{"class":194},"\"in onRejected:\"",[33,3791,961],{"class":135},[33,3793,3794],{"class":39},"\u002F\u002F NOT called! (this catches rejections from the PREVIOUS Promise, not errors in onFulfilled)\n",[33,3796,3797],{"class":35,"line":90},[33,3798,3799],{"class":135},"    )\n",[33,3801,3802,3804,3806,3808,3810,3812,3814,3816,3818,3820,3822],{"class":35,"line":96},[33,3803,457],{"class":135},[33,3805,415],{"class":179},[33,3807,191],{"class":135},[33,3809,2126],{"class":139},[33,3811,394],{"class":118},[33,3813,397],{"class":135},[33,3815,400],{"class":179},[33,3817,191],{"class":135},[33,3819,680],{"class":194},[33,3821,2269],{"class":135},[33,3823,3824],{"class":39},"\u002F\u002F \"caught: in onFulfilled\" (caught here, not in onRejected)\n",[33,3826,3827],{"class":35,"line":102},[33,3828,106],{"emptyLinePlaceholder":105},[33,3830,3831],{"class":35,"line":109},[33,3832,3833],{"class":39},"\u002F\u002F ── .finally doesn't receive the value (and doesn't change it) ──\n",[33,3835,3836,3838,3840,3842,3844,3846],{"class":35,"line":115},[33,3837,440],{"class":122},[33,3839,236],{"class":135},[33,3841,140],{"class":179},[33,3843,191],{"class":135},[33,3845,708],{"class":194},[33,3847,452],{"class":135},[33,3849,3850,3852,3854,3856,3858,3860,3862,3864,3867,3869],{"class":35,"line":158},[33,3851,457],{"class":135},[33,3853,418],{"class":179},[33,3855,183],{"class":135},[33,3857,152],{"class":118},[33,3859,397],{"class":135},[33,3861,400],{"class":179},[33,3863,191],{"class":135},[33,3865,3866],{"class":194},"\"finally\"",[33,3868,577],{"class":135},[33,3870,3871],{"class":39},"\u002F\u002F no argument — finally doesn't get the value\n",[33,3873,3874,3876,3878,3880,3882,3884,3886,3888,3890],{"class":35,"line":164},[33,3875,457],{"class":135},[33,3877,386],{"class":179},[33,3879,191],{"class":135},[33,3881,391],{"class":139},[33,3883,394],{"class":118},[33,3885,397],{"class":135},[33,3887,400],{"class":179},[33,3889,403],{"class":135},[33,3891,3892],{"class":39},"\u002F\u002F \"data\" (finally didn't change the value)\n",[33,3894,3895],{"class":35,"line":170},[33,3896,3897],{"class":39},"\u002F\u002F If finally returns a value or throws, it DOES affect the chain:\n",[33,3899,3900,3902,3904,3906,3908,3910],{"class":35,"line":176},[33,3901,440],{"class":122},[33,3903,236],{"class":135},[33,3905,140],{"class":179},[33,3907,191],{"class":135},[33,3909,708],{"class":194},[33,3911,452],{"class":135},[33,3913,3914,3916,3918,3920,3922,3925,3928],{"class":35,"line":207},[33,3915,457],{"class":135},[33,3917,418],{"class":179},[33,3919,183],{"class":135},[33,3921,152],{"class":118},[33,3923,3924],{"class":194}," \"overridden\"",[33,3926,3927],{"class":135},")  ",[33,3929,3930],{"class":39},"\u002F\u002F returns a value → but the original value is preserved (finally ignores return)\n",[33,3932,3933,3935,3937,3939,3941,3943,3945,3947,3949],{"class":35,"line":213},[33,3934,457],{"class":135},[33,3936,386],{"class":179},[33,3938,191],{"class":135},[33,3940,391],{"class":139},[33,3942,394],{"class":118},[33,3944,397],{"class":135},[33,3946,400],{"class":179},[33,3948,403],{"class":135},[33,3950,3951],{"class":39},"\u002F\u002F \"data\" (finally's return is ignored for non-throwing)\n",[33,3953,3954],{"class":35,"line":218},[33,3955,106],{"emptyLinePlaceholder":105},[33,3957,3958],{"class":35,"line":224},[33,3959,3960],{"class":39},"\u002F\u002F ── Promise.all rejects on FIRST rejection (others keep running) ──\n",[33,3962,3963],{"class":35,"line":252},[33,3964,3965],{"class":39},"\u002F\u002F Promise.all doesn't cancel the other Promises — they keep running (just ignored).\n",[33,3967,3968],{"class":35,"line":287},[33,3969,3970],{"class":39},"\u002F\u002F Use AbortController to actually cancel ongoing fetches.\n",[33,3972,3973],{"class":35,"line":292},[33,3974,106],{"emptyLinePlaceholder":105},[33,3976,3977],{"class":35,"line":298},[33,3978,3979],{"class":39},"\u002F\u002F ── Returning a non-Promise from .then wraps it in Promise.resolve ──\n",[33,3981,3982,3984,3986,3988,3990,3992],{"class":35,"line":326},[33,3983,440],{"class":122},[33,3985,236],{"class":135},[33,3987,140],{"class":179},[33,3989,191],{"class":135},[33,3991,449],{"class":122},[33,3993,452],{"class":135},[33,3995,3996,3998,4000,4002,4004,4006,4008,4010,4012,4014],{"class":35,"line":342},[33,3997,457],{"class":135},[33,3999,386],{"class":179},[33,4001,191],{"class":135},[33,4003,391],{"class":139},[33,4005,394],{"class":118},[33,4007,468],{"class":135},[33,4009,471],{"class":118},[33,4011,474],{"class":122},[33,4013,3927],{"class":135},[33,4015,4016],{"class":39},"\u002F\u002F returns 2 (a number) → Promise.resolve(2) → next .then gets 2\n",[33,4018,4019,4021,4023,4025,4027,4029,4031,4033,4036],{"class":35,"line":358},[33,4020,457],{"class":135},[33,4022,386],{"class":179},[33,4024,191],{"class":135},[33,4026,391],{"class":139},[33,4028,394],{"class":118},[33,4030,2131],{"class":135},[33,4032,400],{"class":179},[33,4034,4035],{"class":135},"(v) });  ",[33,4037,4038],{"class":39},"\u002F\u002F 2\n",[33,4040,4041],{"class":35,"line":375},[33,4042,106],{"emptyLinePlaceholder":105},[33,4044,4045],{"class":35,"line":380},[33,4046,4047],{"class":39},"\u002F\u002F ── Throwing in a .then rejects the returned Promise ──\n",[33,4049,4050,4052,4054,4056],{"class":35,"line":914},[33,4051,440],{"class":122},[33,4053,236],{"class":135},[33,4055,140],{"class":179},[33,4057,781],{"class":135},[33,4059,4060,4062,4064,4066,4068,4070,4072,4074,4076,4078,4080,4082],{"class":35,"line":924},[33,4061,457],{"class":135},[33,4063,386],{"class":179},[33,4065,183],{"class":135},[33,4067,152],{"class":118},[33,4069,794],{"class":135},[33,4071,797],{"class":118},[33,4073,129],{"class":118},[33,4075,273],{"class":179},[33,4077,191],{"class":135},[33,4079,806],{"class":194},[33,4081,809],{"class":135},[33,4083,4084],{"class":39},"\u002F\u002F returns a rejected Promise\n",[33,4086,4087,4089,4091,4093,4095,4097,4099,4101,4104],{"class":35,"line":944},[33,4088,457],{"class":135},[33,4090,415],{"class":179},[33,4092,191],{"class":135},[33,4094,2126],{"class":139},[33,4096,394],{"class":118},[33,4098,397],{"class":135},[33,4100,400],{"class":179},[33,4102,4103],{"class":135},"(e.message));  ",[33,4105,4106],{"class":39},"\u002F\u002F \"boom\"\n",[15,4108,4110],{"id":4109},"quick-quiz","🧠 Quick Quiz",[4112,4113,4114],"p",{},"What's the output?",[20,4116,4117],{"language":22},[24,4118,4120],{"className":26,"code":4119,"language":22,"meta":28,"style":28},"Promise.resolve(\"A\")\n    .then(v => { console.log(v); return \"B\"; })\n    .then(v => { console.log(v); throw \"C\"; })\n    .then(v => console.log(v, \"D\"))\n    .catch(e => console.log(\"E:\", e))\n    .finally(() => console.log(\"F\"));\n",[30,4121,4122,4136,4163,4188,4212,4236],{"__ignoreMap":28},[33,4123,4124,4126,4128,4130,4132,4134],{"class":35,"line":36},[33,4125,440],{"class":122},[33,4127,236],{"class":135},[33,4129,140],{"class":179},[33,4131,191],{"class":135},[33,4133,2060],{"class":194},[33,4135,452],{"class":135},[33,4137,4138,4140,4142,4144,4146,4148,4150,4152,4155,4157,4160],{"class":35,"line":43},[33,4139,457],{"class":135},[33,4141,386],{"class":179},[33,4143,191],{"class":135},[33,4145,391],{"class":139},[33,4147,394],{"class":118},[33,4149,2131],{"class":135},[33,4151,400],{"class":179},[33,4153,4154],{"class":135},"(v); ",[33,4156,2143],{"class":118},[33,4158,4159],{"class":194}," \"B\"",[33,4161,4162],{"class":135},"; })\n",[33,4164,4165,4167,4169,4171,4173,4175,4177,4179,4181,4183,4186],{"class":35,"line":49},[33,4166,457],{"class":135},[33,4168,386],{"class":179},[33,4170,191],{"class":135},[33,4172,391],{"class":139},[33,4174,394],{"class":118},[33,4176,2131],{"class":135},[33,4178,400],{"class":179},[33,4180,4154],{"class":135},[33,4182,797],{"class":118},[33,4184,4185],{"class":194}," \"C\"",[33,4187,4162],{"class":135},[33,4189,4190,4192,4194,4196,4198,4200,4202,4204,4207,4210],{"class":35,"line":55},[33,4191,457],{"class":135},[33,4193,386],{"class":179},[33,4195,191],{"class":135},[33,4197,391],{"class":139},[33,4199,394],{"class":118},[33,4201,397],{"class":135},[33,4203,400],{"class":179},[33,4205,4206],{"class":135},"(v, ",[33,4208,4209],{"class":194},"\"D\"",[33,4211,658],{"class":135},[33,4213,4214,4216,4218,4220,4222,4224,4226,4228,4230,4233],{"class":35,"line":61},[33,4215,457],{"class":135},[33,4217,415],{"class":179},[33,4219,191],{"class":135},[33,4221,2126],{"class":139},[33,4223,394],{"class":118},[33,4225,397],{"class":135},[33,4227,400],{"class":179},[33,4229,191],{"class":135},[33,4231,4232],{"class":194},"\"E:\"",[33,4234,4235],{"class":135},", e))\n",[33,4237,4238,4240,4242,4244,4246,4248,4250,4252,4255],{"class":35,"line":67},[33,4239,457],{"class":135},[33,4241,418],{"class":179},[33,4243,183],{"class":135},[33,4245,152],{"class":118},[33,4247,397],{"class":135},[33,4249,400],{"class":179},[33,4251,191],{"class":135},[33,4253,4254],{"class":194},"\"F\"",[33,4256,4257],{"class":135},"));\n",[4259,4260,4261,4265,4273,4330],"details",{},[4262,4263,4264],"summary",{},"Answer",[24,4266,4271],{"className":4267,"code":4269,"language":4270},[4268],"language-text","A\nB\nE: C\nF\n","text",[30,4272,4269],{"__ignoreMap":28},[4274,4275,4276,4290,4303,4306,4319],"ol",{},[4277,4278,4279,4281,4282,4284,4285,4287,4288],"li",{},[30,4280,2060],{}," — first .then: logs ",[30,4283,2060],{},", returns ",[30,4286,2085],{}," → fulfills with ",[30,4289,2085],{},[4277,4291,4292,4294,4295,4297,4298,4300,4301],{},[30,4293,2085],{}," — second .then: logs ",[30,4296,2085],{},", throws ",[30,4299,2110],{}," → rejects with ",[30,4302,2110],{},[4277,4304,4305],{},"Third .then is SKIPPED (previous rejected)",[4277,4307,4308,4311,4312,4314,4315,4318],{},[30,4309,4310],{},".catch(e => ...)"," — catches ",[30,4313,2110],{},", logs ",[30,4316,4317],{},"\"E: C\""," → fulfills (catch handled it)",[4277,4320,4321,4323,4324,4327,4328],{},[30,4322,4254],{}," — ",[30,4325,4326],{},".finally()"," runs regardless → logs ",[30,4329,4254],{},[4112,4331,4332,4333,4336,4337,4339,4340,4343,4344,4347],{},"The third ",[30,4334,4335],{},".then"," is skipped because the second ",[30,4338,4335],{}," threw (rejected). The ",[30,4341,4342],{},".catch"," catches the rejection, and ",[30,4345,4346],{},".finally"," runs regardless of fulfill\u002Freject.",[4349,4350,4351],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}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 pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}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 .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);}",{"title":28,"searchDepth":43,"depth":43,"links":4353},[4354,4355,4357,4358,4360,4361,4362,4363,4364],{"id":17,"depth":43,"text":18},{"id":409,"depth":43,"text":4356},"Chaining: then, catch, finally",{"id":979,"depth":43,"text":980},{"id":1406,"depth":43,"text":4359},"Promise Composition: all, race, allSettled, any",{"id":2014,"depth":43,"text":2015},{"id":2593,"depth":43,"text":2594},{"id":3181,"depth":43,"text":3182},{"id":3693,"depth":43,"text":3694},{"id":4109,"depth":43,"text":4110},"Deep-dive into JavaScript Promises: the three-state machine, then\u002Fcatch\u002Ffinally chaining, microtask scheduling, Promise composition (all\u002Frace\u002FallSettled\u002Fany), and error propagation semantics. Code-first reference for senior engineers.","md",{},"\u002Fjs\u002F16-promises",{"title":5,"description":4365},"js\u002F16-promises","lR4C8eOrxA98hln6UHf0Vu9g5Ehw7PLJNaqYuX2xQvc",1789924649326]