[{"data":1,"prerenderedAt":3333},["ShallowReactive",2],{"page-\u002Fjs\u002F17-async-await":3},{"id":4,"title":5,"body":6,"description":30,"extension":3327,"meta":3328,"navigation":78,"path":3329,"seo":3330,"stem":3331,"__hash__":3332},"content\u002Fjs\u002F17-async-await.md","17 — Async\u002FAwait",{"type":7,"value":8,"toc":3294},"minimark",[9,13,208,398,622,826,963,1105,1245,1446,1614,1812,1990,2177,2343,2481,2556,2806,2890,3051,3218,3290],[10,11,5],"h1",{"id":12},"_17-asyncawait",[14,15,17,22,109,157],"question-wrapper",{"language":16},"javascript",[18,19,21],"h3",{"id":20},"q1-what-does-the-following-code-actually-log","Q1. What does the following code actually log?",[23,24,25],"code-wrapper",{"language":16},[26,27,31],"pre",{"className":28,"code":29,"language":16,"meta":30,"style":30},"language-javascript shiki shiki-themes github-light github-dark","async function getNum() {\n  return 42;\n}\n\nconst result = getNum();\nconsole.log(result);\n","",[32,33,34,54,67,73,80,97],"code",{"__ignoreMap":30},[35,36,39,43,46,50],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"svdQ7","async",[35,44,45],{"class":41}," function",[35,47,49],{"class":48},"sIsaT"," getNum",[35,51,53],{"class":52},"ssxIu","() {\n",[35,55,57,60,64],{"class":37,"line":56},2,[35,58,59],{"class":41},"  return",[35,61,63],{"class":62},"snvgF"," 42",[35,65,66],{"class":52},";\n",[35,68,70],{"class":37,"line":69},3,[35,71,72],{"class":52},"}\n",[35,74,76],{"class":37,"line":75},4,[35,77,79],{"emptyLinePlaceholder":78},true,"\n",[35,81,83,86,89,92,94],{"class":37,"line":82},5,[35,84,85],{"class":41},"const",[35,87,88],{"class":62}," result",[35,90,91],{"class":41}," =",[35,93,49],{"class":48},[35,95,96],{"class":52},"();\n",[35,98,100,103,106],{"class":37,"line":99},6,[35,101,102],{"class":52},"console.",[35,104,105],{"class":48},"log",[35,107,108],{"class":52},"(result);\n",[110,111,114,123,136,145],"ul",{"className":112},[113],"contains-task-list",[115,116,119,63],"li",{"className":117},[118],"task-list-item",[120,121],"input",{"disabled":78,"type":122},"checkbox",[115,124,126,128,129,132,133],{"className":125},[118],[120,127],{"disabled":78,"type":122}," A ",[32,130,131],{},"Promise"," that resolves to ",[32,134,135],{},"42",[115,137,139,141,142],{"className":138},[118],[120,140],{"disabled":78,"type":122}," ",[32,143,144],{},"undefined",[115,146,148,128,150,152,153,132,155],{"className":147},[118],[120,149],{"disabled":78,"type":122},[32,151,131],{}," that resolves to a ",[32,154,131],{},[32,156,135],{},[158,159,160,164,176],"details",{},[161,162,163],"summary",{},"Show Answer",[165,166,167,171,172,132,174],"p",{},[168,169,170],"strong",{},"Answer:"," B — A ",[32,173,131],{},[32,175,135],{},[165,177,178,181,182,185,186,188,189,192,193,196,197,199,200,203,204,207],{},[168,179,180],{},"Explanation:"," An ",[32,183,184],{},"async function"," always returns a ",[32,187,131],{},", no matter what its body does. A plain ",[32,190,191],{},"return value;"," is automatically wrapped, so ",[32,194,195],{},"getNum()"," immediately returns a (soon-to-be-fulfilled) ",[32,198,131],{}," object, not the raw number — ",[32,201,202],{},"console.log(result)"," prints something like ",[32,205,206],{},"Promise { 42 }",". Option A is the classic beginner mistake of forgetting the auto-wrap. Option D is wrong because JS never nests promises like that — returned promises\u002Fthenables are flattened, not stacked (see Q4).",[14,209,210,214,324,351],{"language":16},[18,211,213],{"id":212},"q2-what-order-do-the-logs-print-in","Q2. What order do the logs print in?",[23,215,216],{"language":16},[26,217,219],{"className":28,"code":218,"language":16,"meta":30,"style":30},"async function delayedLog() {\n  console.log(\"A\");\n  await new Promise(resolve => setTimeout(resolve, 0));\n  console.log(\"B\");\n}\n\ndelayedLog();\nconsole.log(\"C\");\n",[32,220,221,232,249,281,294,298,302,310],{"__ignoreMap":30},[35,222,223,225,227,230],{"class":37,"line":38},[35,224,42],{"class":41},[35,226,45],{"class":41},[35,228,229],{"class":48}," delayedLog",[35,231,53],{"class":52},[35,233,234,237,239,242,246],{"class":37,"line":56},[35,235,236],{"class":52},"  console.",[35,238,105],{"class":48},[35,240,241],{"class":52},"(",[35,243,245],{"class":244},"sJ6F3","\"A\"",[35,247,248],{"class":52},");\n",[35,250,251,254,257,260,262,266,269,272,275,278],{"class":37,"line":69},[35,252,253],{"class":41},"  await",[35,255,256],{"class":41}," new",[35,258,259],{"class":62}," Promise",[35,261,241],{"class":52},[35,263,265],{"class":264},"sCrzJ","resolve",[35,267,268],{"class":41}," =>",[35,270,271],{"class":48}," setTimeout",[35,273,274],{"class":52},"(resolve, ",[35,276,277],{"class":62},"0",[35,279,280],{"class":52},"));\n",[35,282,283,285,287,289,292],{"class":37,"line":75},[35,284,236],{"class":52},[35,286,105],{"class":48},[35,288,241],{"class":52},[35,290,291],{"class":244},"\"B\"",[35,293,248],{"class":52},[35,295,296],{"class":37,"line":82},[35,297,72],{"class":52},[35,299,300],{"class":37,"line":99},[35,301,79],{"emptyLinePlaceholder":78},[35,303,305,308],{"class":37,"line":304},7,[35,306,307],{"class":48},"delayedLog",[35,309,96],{"class":52},[35,311,313,315,317,319,322],{"class":37,"line":312},8,[35,314,102],{"class":52},[35,316,105],{"class":48},[35,318,241],{"class":52},[35,320,321],{"class":244},"\"C\"",[35,323,248],{"class":52},[110,325,327,333,339,345],{"className":326},[113],[115,328,330,332],{"className":329},[118],[120,331],{"disabled":78,"type":122}," A, C, B",[115,334,336,338],{"className":335},[118],[120,337],{"disabled":78,"type":122}," A, B, C",[115,340,342,344],{"className":341},[118],[120,343],{"disabled":78,"type":122}," C, A, B",[115,346,348,350],{"className":347},[118],[120,349],{"disabled":78,"type":122}," Order can't be determined — it's a race condition",[158,352,353,355,360],{},[161,354,163],{},[165,356,357,359],{},[168,358,170],{}," A — A, C, B",[165,361,362,141,364,367,368,371,372,376,377,380,381,383,384,387,388,391,392,394,395,397],{},[168,363,180],{},[168,365,366],{},"Debug"," — ",[32,369,370],{},"await"," only pauses the ",[373,374,375],"em",{},"async function itself",", not the whole program. ",[32,378,379],{},"delayedLog()"," runs synchronously up to the ",[32,382,370],{},", logging \"A\", then immediately hands control back to the caller — so ",[32,385,386],{},"console.log(\"C\")"," runs next. Only after the current synchronous code and the microtask queue drain does the ",[32,389,390],{},"setTimeout(..., 0)"," macrotask fire, resuming ",[32,393,307],{}," and logging \"B\" last. This is the core misconception people bring from single-threaded, blocking languages: ",[32,396,370],{}," does not freeze the whole thread.",[14,399,400,408,536,573],{"language":16},[18,401,403,404,407],{"id":402},"q3-what-does-fetchuser1thenconsolelog-print","Q3. What does ",[32,405,406],{},"fetchUser(1).then(console.log)"," print?",[23,409,410],{"language":16},[26,411,413],{"className":28,"code":412,"language":16,"meta":30,"style":30},"async function fetchUser(id) {\n  try {\n    const res = await Promise.reject(new Error(\"Network down\"));\n    return res;\n  } catch (err) {\n    return err.message;\n  }\n}\n\nfetchUser(1).then(console.log);\n",[32,414,415,432,440,476,484,495,502,507,511,516],{"__ignoreMap":30},[35,416,417,419,421,424,426,429],{"class":37,"line":38},[35,418,42],{"class":41},[35,420,45],{"class":41},[35,422,423],{"class":48}," fetchUser",[35,425,241],{"class":52},[35,427,428],{"class":264},"id",[35,430,431],{"class":52},") {\n",[35,433,434,437],{"class":37,"line":56},[35,435,436],{"class":41},"  try",[35,438,439],{"class":52}," {\n",[35,441,442,445,448,450,453,455,458,461,463,466,469,471,474],{"class":37,"line":69},[35,443,444],{"class":41},"    const",[35,446,447],{"class":62}," res",[35,449,91],{"class":41},[35,451,452],{"class":41}," await",[35,454,259],{"class":62},[35,456,457],{"class":52},".",[35,459,460],{"class":48},"reject",[35,462,241],{"class":52},[35,464,465],{"class":41},"new",[35,467,468],{"class":48}," Error",[35,470,241],{"class":52},[35,472,473],{"class":244},"\"Network down\"",[35,475,280],{"class":52},[35,477,478,481],{"class":37,"line":75},[35,479,480],{"class":41},"    return",[35,482,483],{"class":52}," res;\n",[35,485,486,489,492],{"class":37,"line":82},[35,487,488],{"class":52},"  } ",[35,490,491],{"class":41},"catch",[35,493,494],{"class":52}," (err) {\n",[35,496,497,499],{"class":37,"line":99},[35,498,480],{"class":41},[35,500,501],{"class":52}," err.message;\n",[35,503,504],{"class":37,"line":304},[35,505,506],{"class":52},"  }\n",[35,508,509],{"class":37,"line":312},[35,510,72],{"class":52},[35,512,514],{"class":37,"line":513},9,[35,515,79],{"emptyLinePlaceholder":78},[35,517,519,522,524,527,530,533],{"class":37,"line":518},10,[35,520,521],{"class":48},"fetchUser",[35,523,241],{"class":52},[35,525,526],{"class":62},"1",[35,528,529],{"class":52},").",[35,531,532],{"class":48},"then",[35,534,535],{"class":52},"(console.log);\n",[110,537,539,548,556,563],{"className":538},[113],[115,540,542,544,545],{"className":541},[118],[120,543],{"disabled":78,"type":122}," Throws an uncaught ",[32,546,547],{},"Error: Network down",[115,549,551,553,554],{"className":550},[118],[120,552],{"disabled":78,"type":122}," Logs ",[32,555,144],{},[115,557,559,553,561],{"className":558},[118],[120,560],{"disabled":78,"type":122},[32,562,473],{},[115,564,566,568,569,572],{"className":565},[118],[120,567],{"disabled":78,"type":122}," Logs the ",[32,570,571],{},"Error"," object itself",[158,574,575,577,584],{},[161,576,163],{},[165,578,579,581,582],{},[168,580,170],{}," C — Logs ",[32,583,473],{},[165,585,586,141,588,590,591,593,594,597,598,600,601,604,605,608,609,611,612,614,615,618,619,621],{},[168,587,180],{},[32,589,370],{}," on a rejected promise throws the rejection reason right at the ",[32,592,370],{}," expression, exactly like a synchronous ",[32,595,596],{},"throw",". Here that's the ",[32,599,571],{}," object, which the ",[32,602,603],{},"catch (err)"," block receives; ",[32,606,607],{},"err.message"," pulls out the string ",[32,610,473],{},", which is what ",[32,613,521],{}," returns (and therefore resolves its own promise with). Option D is wrong because ",[32,616,617],{},".message"," extracts the string, not the ",[32,620,571],{}," instance. Option A is wrong because the rejection is caught locally, so it never escapes as uncaught.",[14,623,624,628,743,793],{"language":16},[18,625,627],{"id":626},"q4-what-does-this-log","Q4. What does this log?",[23,629,630],{"language":16},[26,631,633],{"className":28,"code":632,"language":16,"meta":30,"style":30},"async function inner() {\n  return Promise.resolve(\"done\");\n}\n\nasync function outer() {\n  const value = await inner();\n  return value;\n}\n\nouter().then(v => console.log(typeof v, v));\n",[32,634,635,646,663,667,671,682,698,705,709,713],{"__ignoreMap":30},[35,636,637,639,641,644],{"class":37,"line":38},[35,638,42],{"class":41},[35,640,45],{"class":41},[35,642,643],{"class":48}," inner",[35,645,53],{"class":52},[35,647,648,650,652,654,656,658,661],{"class":37,"line":56},[35,649,59],{"class":41},[35,651,259],{"class":62},[35,653,457],{"class":52},[35,655,265],{"class":48},[35,657,241],{"class":52},[35,659,660],{"class":244},"\"done\"",[35,662,248],{"class":52},[35,664,665],{"class":37,"line":69},[35,666,72],{"class":52},[35,668,669],{"class":37,"line":75},[35,670,79],{"emptyLinePlaceholder":78},[35,672,673,675,677,680],{"class":37,"line":82},[35,674,42],{"class":41},[35,676,45],{"class":41},[35,678,679],{"class":48}," outer",[35,681,53],{"class":52},[35,683,684,687,690,692,694,696],{"class":37,"line":99},[35,685,686],{"class":41},"  const",[35,688,689],{"class":62}," value",[35,691,91],{"class":41},[35,693,452],{"class":41},[35,695,643],{"class":48},[35,697,96],{"class":52},[35,699,700,702],{"class":37,"line":304},[35,701,59],{"class":41},[35,703,704],{"class":52}," value;\n",[35,706,707],{"class":37,"line":312},[35,708,72],{"class":52},[35,710,711],{"class":37,"line":513},[35,712,79],{"emptyLinePlaceholder":78},[35,714,715,718,721,723,725,728,730,733,735,737,740],{"class":37,"line":518},[35,716,717],{"class":48},"outer",[35,719,720],{"class":52},"().",[35,722,532],{"class":48},[35,724,241],{"class":52},[35,726,727],{"class":264},"v",[35,729,268],{"class":41},[35,731,732],{"class":52}," console.",[35,734,105],{"class":48},[35,736,241],{"class":52},[35,738,739],{"class":41},"typeof",[35,741,742],{"class":52}," v, v));\n",[110,744,746,762,770,778],{"className":745},[113],[115,747,749,141,751,754,755,757,758,761],{"className":748},[118],[120,750],{"disabled":78,"type":122},[32,752,753],{},"object"," (an unresolved ",[32,756,131],{},", ",[32,759,760],{},"done"," never appears)",[115,763,765,141,767],{"className":764},[118],[120,766],{"disabled":78,"type":122},[32,768,769],{},"string done",[115,771,773,141,775],{"className":772},[118],[120,774],{"disabled":78,"type":122},[32,776,777],{},"undefined undefined",[115,779,781,783,784,787,788,790,791],{"className":780},[118],[120,782],{"disabled":78,"type":122}," Throws — you can't ",[32,785,786],{},"return"," a ",[32,789,131],{}," from an ",[32,792,184],{},[158,794,795,797,804],{},[161,796,163],{},[165,798,799,801,802],{},[168,800,170],{}," B — ",[32,803,769],{},[165,805,806,808,809,811,812,815,816,818,819,822,823,825],{},[168,807,180],{}," Returning a promise (or any thenable) from an ",[32,810,184],{}," doesn't create a promise-wrapped-in-a-promise — the outer promise is flattened to adopt the state and value of the returned one. So ",[32,813,814],{},"inner()"," effectively resolves with ",[32,817,660],{},", and ",[32,820,821],{},"await inner()"," in ",[32,824,717],{}," unwraps that down to the plain string. Option A represents the common \"double-wrapping\" misconception. Option D is false: returning a promise from an async function is completely normal and is exactly how flattening is triggered.",[14,827,828,840,900,927],{"language":16},[18,829,831,832,835,836,839],{"id":830},"q5-fetchuser-and-fetchstats-are-independent-neither-depends-on-the-others-result-and-each-takes-300ms","Q5. ",[32,833,834],{},"fetchUser()"," and ",[32,837,838],{},"fetchStats()"," are independent — neither depends on the other's result, and each takes ~300ms.",[23,841,842],{"language":16},[26,843,845],{"className":28,"code":844,"language":16,"meta":30,"style":30},"async function loadDashboard() {\n  const user = await fetchUser();\n  const stats = await fetchStats();\n  return { user, stats };\n}\n",[32,846,847,858,873,889,896],{"__ignoreMap":30},[35,848,849,851,853,856],{"class":37,"line":38},[35,850,42],{"class":41},[35,852,45],{"class":41},[35,854,855],{"class":48}," loadDashboard",[35,857,53],{"class":52},[35,859,860,862,865,867,869,871],{"class":37,"line":56},[35,861,686],{"class":41},[35,863,864],{"class":62}," user",[35,866,91],{"class":41},[35,868,452],{"class":41},[35,870,423],{"class":48},[35,872,96],{"class":52},[35,874,875,877,880,882,884,887],{"class":37,"line":69},[35,876,686],{"class":41},[35,878,879],{"class":62}," stats",[35,881,91],{"class":41},[35,883,452],{"class":41},[35,885,886],{"class":48}," fetchStats",[35,888,96],{"class":52},[35,890,891,893],{"class":37,"line":75},[35,892,59],{"class":41},[35,894,895],{"class":52}," { user, stats };\n",[35,897,898],{"class":37,"line":82},[35,899,72],{"class":52},[110,901,903,909,915,921],{"className":902},[113],[115,904,906,908],{"className":905},[118],[120,907],{"disabled":78,"type":122}," ~150ms",[115,910,912,914],{"className":911},[118],[120,913],{"disabled":78,"type":122}," ~300ms",[115,916,918,920],{"className":917},[118],[120,919],{"disabled":78,"type":122}," Indeterminate — depends on the event loop",[115,922,924,926],{"className":923},[118],[120,925],{"disabled":78,"type":122}," ~600ms",[158,928,929,931,936],{},[161,930,163],{},[165,932,933,935],{},[168,934,170],{}," D — ~600ms",[165,937,938,141,940,367,943,945,946,949,950,952,953,955,956,958,959,962],{},[168,939,180],{},[168,941,942],{},"Performance",[32,944,838],{}," isn't even ",[373,947,948],{},"called"," until the ",[32,951,370],{}," on ",[32,954,834],{}," finishes, so the two 300ms operations run back-to-back instead of overlapping, even though nothing about them requires that. This is one of the most common async\u002Fawait performance footguns: writing two independent operations as consecutive ",[32,957,370],{}," lines silently serializes them. The fix is to start both before awaiting either (Q6) or use ",[32,960,961],{},"Promise.all"," (Q7).",[14,964,965,969,1048,1078],{"language":16},[18,966,968],{"id":967},"q6-same-independent-300ms-calls-as-q5-but-written-like-this-instead","Q6. Same independent, ~300ms calls as Q5, but written like this instead:",[23,970,971],{"language":16},[26,972,974],{"className":28,"code":973,"language":16,"meta":30,"style":30},"async function loadDashboard() {\n  const userPromise = fetchUser();\n  const statsPromise = fetchStats();\n  const user = await userPromise;\n  const stats = await statsPromise;\n  return { user, stats };\n}\n",[32,975,976,986,999,1012,1025,1038,1044],{"__ignoreMap":30},[35,977,978,980,982,984],{"class":37,"line":38},[35,979,42],{"class":41},[35,981,45],{"class":41},[35,983,855],{"class":48},[35,985,53],{"class":52},[35,987,988,990,993,995,997],{"class":37,"line":56},[35,989,686],{"class":41},[35,991,992],{"class":62}," userPromise",[35,994,91],{"class":41},[35,996,423],{"class":48},[35,998,96],{"class":52},[35,1000,1001,1003,1006,1008,1010],{"class":37,"line":69},[35,1002,686],{"class":41},[35,1004,1005],{"class":62}," statsPromise",[35,1007,91],{"class":41},[35,1009,886],{"class":48},[35,1011,96],{"class":52},[35,1013,1014,1016,1018,1020,1022],{"class":37,"line":75},[35,1015,686],{"class":41},[35,1017,864],{"class":62},[35,1019,91],{"class":41},[35,1021,452],{"class":41},[35,1023,1024],{"class":52}," userPromise;\n",[35,1026,1027,1029,1031,1033,1035],{"class":37,"line":82},[35,1028,686],{"class":41},[35,1030,879],{"class":62},[35,1032,91],{"class":41},[35,1034,452],{"class":41},[35,1036,1037],{"class":52}," statsPromise;\n",[35,1039,1040,1042],{"class":37,"line":99},[35,1041,59],{"class":41},[35,1043,895],{"class":52},[35,1045,1046],{"class":37,"line":304},[35,1047,72],{"class":52},[110,1049,1051,1057,1063,1069],{"className":1050},[113],[115,1052,1054,1056],{"className":1053},[118],[120,1055],{"disabled":78,"type":122}," ~300ms total — both calls start immediately and run concurrently",[115,1058,1060,1062],{"className":1059},[118],[120,1061],{"disabled":78,"type":122}," ~600ms — identical timing to Q5",[115,1064,1066,1068],{"className":1065},[118],[120,1067],{"disabled":78,"type":122}," Throws a race-condition error since both are in flight at once",[115,1070,1072,1074,1075,1077],{"className":1071},[118],[120,1073],{"disabled":78,"type":122}," ~300ms, but only if ",[32,1076,521],{}," happens to resolve first",[158,1079,1080,1082,1087],{},[161,1081,163],{},[165,1083,1084,1086],{},[168,1085,170],{}," A — ~300ms total — both calls start immediately and run concurrently",[165,1088,1089,141,1091,1093,1094,835,1096,1098,1099,1101,1102,1104],{},[168,1090,180],{},[168,1092,942],{}," — Calling ",[32,1095,834],{},[32,1097,838],{}," without immediately awaiting them kicks off both underlying operations right away; they run concurrently while the async function is paused. The later ",[32,1100,370],{}," calls just wait on promises that are already in flight, so total wall time is bounded by the slower of the two (~300ms), not their sum. Option D is a trap: correctness here doesn't depend on which resolves first, since each ",[32,1103,370],{}," targets its own dedicated promise variable.",[14,1106,1107,1111,1182,1212],{"language":16},[18,1108,1110],{"id":1109},"q7-how-does-this-version-compare-to-q6s-manual-start-both-then-await-both-pattern","Q7. How does this version compare to Q6's manual \"start both, then await both\" pattern?",[23,1112,1113],{"language":16},[26,1114,1116],{"className":28,"code":1115,"language":16,"meta":30,"style":30},"async function loadDashboard() {\n  const [user, stats] = await Promise.all([fetchUser(), fetchStats()]);\n  return { user, stats };\n}\n",[32,1117,1118,1128,1172,1178],{"__ignoreMap":30},[35,1119,1120,1122,1124,1126],{"class":37,"line":38},[35,1121,42],{"class":41},[35,1123,45],{"class":41},[35,1125,855],{"class":48},[35,1127,53],{"class":52},[35,1129,1130,1132,1135,1138,1140,1143,1146,1149,1151,1153,1155,1158,1161,1163,1166,1169],{"class":37,"line":56},[35,1131,686],{"class":41},[35,1133,1134],{"class":52}," [",[35,1136,1137],{"class":62},"user",[35,1139,757],{"class":52},[35,1141,1142],{"class":62},"stats",[35,1144,1145],{"class":52},"] ",[35,1147,1148],{"class":41},"=",[35,1150,452],{"class":41},[35,1152,259],{"class":62},[35,1154,457],{"class":52},[35,1156,1157],{"class":48},"all",[35,1159,1160],{"class":52},"([",[35,1162,521],{"class":48},[35,1164,1165],{"class":52},"(), ",[35,1167,1168],{"class":48},"fetchStats",[35,1170,1171],{"class":52},"()]);\n",[35,1173,1174,1176],{"class":37,"line":69},[35,1175,59],{"class":41},[35,1177,895],{"class":52},[35,1179,1180],{"class":37,"line":75},[35,1181,72],{"class":52},[110,1183,1185,1194,1200,1206],{"className":1184},[113],[115,1186,1188,1190,1191,1193],{"className":1187},[118],[120,1189],{"disabled":78,"type":122}," It's slower — ",[32,1192,961],{}," adds meaningful overhead",[115,1195,1197,1199],{"className":1196},[118],[120,1198],{"disabled":78,"type":122}," It behaves exactly like the sequential version in Q5",[115,1201,1203,1205],{"className":1202},[118],[120,1204],{"disabled":78,"type":122}," It runs the same operations concurrently as Q6, as one idiomatic expression, and fails fast if any promise rejects",[115,1207,1209,1211],{"className":1208},[118],[120,1210],{"disabled":78,"type":122}," It only works when there are exactly two promises in the array",[158,1213,1214,1216,1221],{},[161,1215,163],{},[165,1217,1218,1220],{},[168,1219,170],{}," C — It runs the same operations concurrently as Q6, as one idiomatic expression, and fails fast if any promise rejects",[165,1222,1223,141,1225,367,1228,1231,1232,835,1234,1236,1237,1240,1241,1244],{},[168,1224,180],{},[168,1226,1227],{},"Idiom",[32,1229,1230],{},"Promise.all([...])"," is the standard, idiomatic way to fan out independent async work: ",[32,1233,834],{},[32,1235,838],{}," are both invoked synchronously when the array literal is built, so timing matches Q6, just more concisely. Its key extra behavior is fail-fast semantics: the combined promise rejects as soon as ",[373,1238,1239],{},"any"," input promise rejects, without waiting for the rest (use ",[32,1242,1243],{},"Promise.allSettled"," if you need every result regardless of individual failures).",[14,1246,1247,1255,1351,1397],{"language":16},[18,1248,1250,1251,1254],{"id":1249},"q8-riskyoperation-returns-a-promise-that-may-reject-what-happens-if-it-does","Q8. ",[32,1252,1253],{},"riskyOperation()"," returns a promise that may reject. What happens if it does?",[23,1256,1257],{"language":16},[26,1258,1260],{"className":28,"code":1259,"language":16,"meta":30,"style":30},"async function process() {\n  const promise = riskyOperation();\n  try {\n    doSomethingElse();\n  } catch (err) {\n    console.log(\"caught:\", err.message);\n  }\n  const result = await promise;\n  return result;\n}\n",[32,1261,1262,1273,1287,1293,1300,1308,1323,1327,1340,1347],{"__ignoreMap":30},[35,1263,1264,1266,1268,1271],{"class":37,"line":38},[35,1265,42],{"class":41},[35,1267,45],{"class":41},[35,1269,1270],{"class":48}," process",[35,1272,53],{"class":52},[35,1274,1275,1277,1280,1282,1285],{"class":37,"line":56},[35,1276,686],{"class":41},[35,1278,1279],{"class":62}," promise",[35,1281,91],{"class":41},[35,1283,1284],{"class":48}," riskyOperation",[35,1286,96],{"class":52},[35,1288,1289,1291],{"class":37,"line":69},[35,1290,436],{"class":41},[35,1292,439],{"class":52},[35,1294,1295,1298],{"class":37,"line":75},[35,1296,1297],{"class":48},"    doSomethingElse",[35,1299,96],{"class":52},[35,1301,1302,1304,1306],{"class":37,"line":82},[35,1303,488],{"class":52},[35,1305,491],{"class":41},[35,1307,494],{"class":52},[35,1309,1310,1313,1315,1317,1320],{"class":37,"line":99},[35,1311,1312],{"class":52},"    console.",[35,1314,105],{"class":48},[35,1316,241],{"class":52},[35,1318,1319],{"class":244},"\"caught:\"",[35,1321,1322],{"class":52},", err.message);\n",[35,1324,1325],{"class":37,"line":304},[35,1326,506],{"class":52},[35,1328,1329,1331,1333,1335,1337],{"class":37,"line":312},[35,1330,686],{"class":41},[35,1332,88],{"class":62},[35,1334,91],{"class":41},[35,1336,452],{"class":41},[35,1338,1339],{"class":52}," promise;\n",[35,1341,1342,1344],{"class":37,"line":513},[35,1343,59],{"class":41},[35,1345,1346],{"class":52}," result;\n",[35,1348,1349],{"class":37,"line":518},[35,1350,72],{"class":52},[110,1352,1354,1370,1383,1389],{"className":1353},[113],[115,1355,1357,1359,1360,1362,1363,1366,1367],{"className":1356},[118],[120,1358],{"disabled":78,"type":122}," It's caught by the ",[32,1361,491],{}," block, since ",[32,1364,1365],{},"promise"," was created before the ",[32,1368,1369],{},"try",[115,1371,1373,1375,1376,1378,1379,1382],{"className":1372},[118],[120,1374],{"disabled":78,"type":122}," It is NOT caught by the ",[32,1377,491],{}," block — the rejection propagates out of ",[32,1380,1381],{},"process()"," as a rejected promise",[115,1384,1386,1388],{"className":1385},[118],[120,1387],{"disabled":78,"type":122}," The program throws synchronously and crashes immediately",[115,1390,1392,1394,1395],{"className":1391},[118],[120,1393],{"disabled":78,"type":122}," The runtime automatically retries ",[32,1396,1253],{},[158,1398,1399,1401,1410],{},[161,1400,163],{},[165,1402,1403,1405,1406,1378,1408,1382],{},[168,1404,170],{}," B — It is NOT caught by the ",[32,1407,491],{},[32,1409,1381],{},[165,1411,1412,141,1414,367,1416,1419,1420,1423,1424,1426,1427,1430,1431,1433,1434,1436,1437,1440,1441,1443,1444,457],{},[168,1413,180],{},[168,1415,366],{},[32,1417,1418],{},"try\u002Fcatch"," only catches errors from code that runs ",[373,1421,1422],{},"textually inside"," the ",[32,1425,1369],{}," block. Here ",[32,1428,1429],{},"await promise"," sits after the ",[32,1432,1418],{}," entirely, so its rejection isn't caught locally at all — it makes ",[32,1435,1381],{},"'s own returned promise reject. Where the promise was ",[373,1438,1439],{},"created"," is irrelevant; what matters is where the ",[32,1442,370],{}," keyword itself sits relative to ",[32,1445,1418],{},[14,1447,1448,1461,1539,1585],{"language":16},[18,1449,1451,1452,1454,1455,1457,1458,1460],{"id":1450},"q9-now-the-await-has-moved-inside-the-try-block-even-though-riskyoperation-is-still-called-before-it","Q9. Now the ",[32,1453,370],{}," has moved inside the ",[32,1456,1369],{}," block, even though ",[32,1459,1253],{}," is still called before it:",[23,1462,1463],{"language":16},[26,1464,1466],{"className":28,"code":1465,"language":16,"meta":30,"style":30},"async function process() {\n  const promise = riskyOperation();\n  try {\n    const result = await promise;\n    return result;\n  } catch (err) {\n    return \"fallback\";\n  }\n}\n",[32,1467,1468,1478,1490,1496,1508,1514,1522,1531,1535],{"__ignoreMap":30},[35,1469,1470,1472,1474,1476],{"class":37,"line":38},[35,1471,42],{"class":41},[35,1473,45],{"class":41},[35,1475,1270],{"class":48},[35,1477,53],{"class":52},[35,1479,1480,1482,1484,1486,1488],{"class":37,"line":56},[35,1481,686],{"class":41},[35,1483,1279],{"class":62},[35,1485,91],{"class":41},[35,1487,1284],{"class":48},[35,1489,96],{"class":52},[35,1491,1492,1494],{"class":37,"line":69},[35,1493,436],{"class":41},[35,1495,439],{"class":52},[35,1497,1498,1500,1502,1504,1506],{"class":37,"line":75},[35,1499,444],{"class":41},[35,1501,88],{"class":62},[35,1503,91],{"class":41},[35,1505,452],{"class":41},[35,1507,1339],{"class":52},[35,1509,1510,1512],{"class":37,"line":82},[35,1511,480],{"class":41},[35,1513,1346],{"class":52},[35,1515,1516,1518,1520],{"class":37,"line":99},[35,1517,488],{"class":52},[35,1519,491],{"class":41},[35,1521,494],{"class":52},[35,1523,1524,1526,1529],{"class":37,"line":304},[35,1525,480],{"class":41},[35,1527,1528],{"class":244}," \"fallback\"",[35,1530,66],{"class":52},[35,1532,1533],{"class":37,"line":312},[35,1534,506],{"class":52},[35,1536,1537],{"class":37,"line":513},[35,1538,72],{"class":52},[110,1540,1542,1553,1565,1574],{"className":1541},[113],[115,1543,1545,1547,1548,1550,1551],{"className":1544},[118],[120,1546],{"disabled":78,"type":122}," The ",[32,1549,491],{}," block never runs because the promise was created outside the ",[32,1552,1369],{},[115,1554,1556,1558,1559,1561,1562,1564],{"className":1555},[118],[120,1557],{"disabled":78,"type":122}," This is a syntax error — you can't ",[32,1560,370],{}," a promise defined outside a ",[32,1563,1369],{}," block",[115,1566,1568,1570,1571,1573],{"className":1567},[118],[120,1569],{"disabled":78,"type":122}," An unhandled rejection warning still fires even though ",[32,1572,491],{}," runs",[115,1575,1577,1547,1579,1581,1582,1584],{"className":1576},[118],[120,1578],{"disabled":78,"type":122},[32,1580,491],{}," block correctly handles the rejection, because what matters is where ",[32,1583,370],{}," is written, not where the promise was created",[158,1586,1587,1589,1598],{},[161,1588,163],{},[165,1590,1591,1593,1594,1581,1596,1584],{},[168,1592,170],{}," D — The ",[32,1595,491],{},[32,1597,370],{},[165,1599,1600,141,1602,1604,1605,1607,1608,1610,1611,1613],{},[168,1601,180],{},[168,1603,366],{}," — This mirrors Q8 from the other direction: a promise can be constructed anywhere; only the location of the ",[32,1606,370],{}," expression relative to ",[32,1609,1418],{}," determines whether its rejection is caught. No unhandled-rejection warning fires here, because a catch handler is effectively attached (via ",[32,1612,370],{},"'s internal machinery) before the rejection is ever reported as unhandled. Options A and C represent the same \"creation site matters\" misconception this pair of questions is built to correct.",[14,1615,1616,1631,1725,1766],{"language":16},[18,1617,1619,1620,1623,1624,1626,1627,1630],{"id":1618},"q10-saveuser-is-async-what-order-do-the-logs-print-in-when-handlesubmituser-runs","Q10. ",[32,1621,1622],{},"saveUser"," is ",[32,1625,42],{},". What order do the logs print in when ",[32,1628,1629],{},"handleSubmit(user)"," runs?",[23,1632,1633],{"language":16},[26,1634,1636],{"className":28,"code":1635,"language":16,"meta":30,"style":30},"async function saveUser(user) {\n  await db.insert(user);\n  console.log(\"saved\");\n}\n\nfunction handleSubmit(user) {\n  saveUser(user);\n  console.log(\"submitted\");\n}\n",[32,1637,1638,1653,1666,1679,1683,1687,1701,1708,1721],{"__ignoreMap":30},[35,1639,1640,1642,1644,1647,1649,1651],{"class":37,"line":38},[35,1641,42],{"class":41},[35,1643,45],{"class":41},[35,1645,1646],{"class":48}," saveUser",[35,1648,241],{"class":52},[35,1650,1137],{"class":264},[35,1652,431],{"class":52},[35,1654,1655,1657,1660,1663],{"class":37,"line":56},[35,1656,253],{"class":41},[35,1658,1659],{"class":52}," db.",[35,1661,1662],{"class":48},"insert",[35,1664,1665],{"class":52},"(user);\n",[35,1667,1668,1670,1672,1674,1677],{"class":37,"line":69},[35,1669,236],{"class":52},[35,1671,105],{"class":48},[35,1673,241],{"class":52},[35,1675,1676],{"class":244},"\"saved\"",[35,1678,248],{"class":52},[35,1680,1681],{"class":37,"line":75},[35,1682,72],{"class":52},[35,1684,1685],{"class":37,"line":82},[35,1686,79],{"emptyLinePlaceholder":78},[35,1688,1689,1692,1695,1697,1699],{"class":37,"line":99},[35,1690,1691],{"class":41},"function",[35,1693,1694],{"class":48}," handleSubmit",[35,1696,241],{"class":52},[35,1698,1137],{"class":264},[35,1700,431],{"class":52},[35,1702,1703,1706],{"class":37,"line":304},[35,1704,1705],{"class":48},"  saveUser",[35,1707,1665],{"class":52},[35,1709,1710,1712,1714,1716,1719],{"class":37,"line":312},[35,1711,236],{"class":52},[35,1713,105],{"class":48},[35,1715,241],{"class":52},[35,1717,1718],{"class":244},"\"submitted\"",[35,1720,248],{"class":52},[35,1722,1723],{"class":37,"line":513},[35,1724,72],{"class":52},[110,1726,1728,1742,1751,1760],{"className":1727},[113],[115,1729,1731,1733,1734,1737,1738,1741],{"className":1730},[118],[120,1732],{"disabled":78,"type":122}," \"submitted\" logs before \"saved\", because ",[32,1735,1736],{},"saveUser(user)"," isn't awaited so ",[32,1739,1740],{},"handleSubmit"," doesn't pause for it",[115,1743,1745,1747,1748,1750],{"className":1744},[118],[120,1746],{"disabled":78,"type":122}," \"saved\" always logs first, because ",[32,1749,1622],{}," was called first",[115,1752,1754,1756,1757,1759],{"className":1753},[118],[120,1755],{"disabled":78,"type":122}," Only \"submitted\" logs — \"saved\" never logs since ",[32,1758,1622],{}," wasn't awaited",[115,1761,1763,1765],{"className":1762},[118],[120,1764],{"disabled":78,"type":122}," This throws a runtime error: \"must await async function\"",[158,1767,1768,1770,1779],{},[161,1769,163],{},[165,1771,1772,1774,1775,1737,1777,1741],{},[168,1773,170],{}," A — \"submitted\" logs before \"saved\", because ",[32,1776,1736],{},[32,1778,1740],{},[165,1780,1781,141,1783,1785,1786,1788,1789,1792,1793,1795,1796,1798,1799,1802,1803,1805,1806,1808,1809,1811],{},[168,1782,180],{},[168,1784,366],{}," — Calling an async function without ",[32,1787,370],{}," still ",[373,1790,1791],{},"runs"," it — the call isn't skipped, only the pausing is. ",[32,1794,1740],{}," fires ",[32,1797,1736],{},", immediately gets back a promise it ignores, and moves straight to ",[32,1800,1801],{},"console.log(\"submitted\")",". Meanwhile ",[32,1804,1622],{},"'s own ",[32,1807,370],{}," yields to the microtask queue, so its ",[32,1810,1676],{}," log lands afterward. Option C is the common wrong guess — the function body absolutely still executes, just asynchronously and unobserved.",[14,1813,1814,1823,1898,1949],{"language":16},[18,1815,1817,1818,1623,1820,1822],{"id":1816},"q11-saveuser-is-async-and-may-reject-internally-what-happens-when-it-does","Q11. ",[32,1819,1622],{},[32,1821,42],{}," and may reject internally. What happens when it does?",[23,1824,1825],{"language":16},[26,1826,1828],{"className":28,"code":1827,"language":16,"meta":30,"style":30},"async function handleSubmit(user) {\n  try {\n    saveUser(user);\n    console.log(\"submitted\");\n  } catch (err) {\n    console.log(\"error:\", err.message);\n  }\n}\n",[32,1829,1830,1844,1850,1857,1869,1877,1890,1894],{"__ignoreMap":30},[35,1831,1832,1834,1836,1838,1840,1842],{"class":37,"line":38},[35,1833,42],{"class":41},[35,1835,45],{"class":41},[35,1837,1694],{"class":48},[35,1839,241],{"class":52},[35,1841,1137],{"class":264},[35,1843,431],{"class":52},[35,1845,1846,1848],{"class":37,"line":56},[35,1847,436],{"class":41},[35,1849,439],{"class":52},[35,1851,1852,1855],{"class":37,"line":69},[35,1853,1854],{"class":48},"    saveUser",[35,1856,1665],{"class":52},[35,1858,1859,1861,1863,1865,1867],{"class":37,"line":75},[35,1860,1312],{"class":52},[35,1862,105],{"class":48},[35,1864,241],{"class":52},[35,1866,1718],{"class":244},[35,1868,248],{"class":52},[35,1870,1871,1873,1875],{"class":37,"line":82},[35,1872,488],{"class":52},[35,1874,491],{"class":41},[35,1876,494],{"class":52},[35,1878,1879,1881,1883,1885,1888],{"class":37,"line":99},[35,1880,1312],{"class":52},[35,1882,105],{"class":48},[35,1884,241],{"class":52},[35,1886,1887],{"class":244},"\"error:\"",[35,1889,1322],{"class":52},[35,1891,1892],{"class":37,"line":304},[35,1893,506],{"class":52},[35,1895,1896],{"class":37,"line":312},[35,1897,72],{"class":52},[110,1899,1901,1913,1925,1940],{"className":1900},[113],[115,1902,1904,1547,1906,1908,1909,1912],{"className":1903},[118],[120,1905],{"disabled":78,"type":122},[32,1907,491],{}," block logs ",[32,1910,1911],{},"\"error: ...\""," as expected",[115,1914,1916,1918,1919,1921,1922,1924],{"className":1915},[118],[120,1917],{"disabled":78,"type":122}," It throws synchronously and crashes ",[32,1920,1740],{}," before ",[32,1923,1718],{}," logs",[115,1926,1928,1547,1930,1932,1933,1936,1937,1939],{"className":1927},[118],[120,1929],{"disabled":78,"type":122},[32,1931,491],{}," block never runs — instead an unhandled promise rejection occurs elsewhere, since nothing awaits or ",[32,1934,1935],{},".catch","es ",[32,1938,1622],{},"'s returned promise",[115,1941,1943,1945,1946,1948],{"className":1942},[118],[120,1944],{"disabled":78,"type":122}," JavaScript silently converts the missed ",[32,1947,370],{}," into a synchronous call",[158,1950,1951,1953,1964],{},[161,1952,163],{},[165,1954,1955,1957,1958,1932,1960,1936,1962,1939],{},[168,1956,170],{}," C — The ",[32,1959,491],{},[32,1961,1935],{},[32,1963,1622],{},[165,1965,1966,141,1968,1970,1971,1973,1974,1976,1977,1979,1980,1982,1983,1986,1987,1989],{},[168,1967,180],{},[168,1969,366],{}," — Because ",[32,1972,1736],{}," isn't awaited, its returned promise is orphaned; there's no ",[32,1975,370],{}," linking its eventual rejection back into this ",[32,1978,1418],{},", so the local ",[32,1981,491],{}," simply never sees it. The rejection instead surfaces later as an unhandled promise rejection (Node's ",[32,1984,1985],{},"unhandledRejection"," event, or a browser console warning). This is one of the most common real-world async\u002Fawait bugs — forgetting a single ",[32,1988,370],{}," silently defeats the surrounding error handling.",[14,1991,1992,2005,2100,2133],{"language":16},[18,1993,1995,1996,1623,1999,2001,2002,1630],{"id":1994},"q12-saveitem-is-async-what-happens-when-processall-runs","Q12. ",[32,1997,1998],{},"saveItem",[32,2000,42],{},". What happens when ",[32,2003,2004],{},"processAll",[23,2006,2007],{"language":16},[26,2008,2010],{"className":28,"code":2009,"language":16,"meta":30,"style":30},"async function processAll(items) {\n  items.forEach(async (item) => {\n    await saveItem(item);\n    console.log(\"saved\", item.id);\n  });\n  console.log(\"all done\");\n}\n",[32,2011,2012,2028,2054,2065,2078,2083,2096],{"__ignoreMap":30},[35,2013,2014,2016,2018,2021,2023,2026],{"class":37,"line":38},[35,2015,42],{"class":41},[35,2017,45],{"class":41},[35,2019,2020],{"class":48}," processAll",[35,2022,241],{"class":52},[35,2024,2025],{"class":264},"items",[35,2027,431],{"class":52},[35,2029,2030,2033,2036,2038,2040,2043,2046,2049,2052],{"class":37,"line":56},[35,2031,2032],{"class":52},"  items.",[35,2034,2035],{"class":48},"forEach",[35,2037,241],{"class":52},[35,2039,42],{"class":41},[35,2041,2042],{"class":52}," (",[35,2044,2045],{"class":264},"item",[35,2047,2048],{"class":52},") ",[35,2050,2051],{"class":41},"=>",[35,2053,439],{"class":52},[35,2055,2056,2059,2062],{"class":37,"line":69},[35,2057,2058],{"class":41},"    await",[35,2060,2061],{"class":48}," saveItem",[35,2063,2064],{"class":52},"(item);\n",[35,2066,2067,2069,2071,2073,2075],{"class":37,"line":75},[35,2068,1312],{"class":52},[35,2070,105],{"class":48},[35,2072,241],{"class":52},[35,2074,1676],{"class":244},[35,2076,2077],{"class":52},", item.id);\n",[35,2079,2080],{"class":37,"line":82},[35,2081,2082],{"class":52},"  });\n",[35,2084,2085,2087,2089,2091,2094],{"class":37,"line":99},[35,2086,236],{"class":52},[35,2088,105],{"class":48},[35,2090,241],{"class":52},[35,2092,2093],{"class":244},"\"all done\"",[35,2095,248],{"class":52},[35,2097,2098],{"class":37,"line":304},[35,2099,72],{"class":52},[110,2101,2103,2109,2118,2127],{"className":2102},[113],[115,2104,2106,2108],{"className":2105},[118],[120,2107],{"disabled":78,"type":122}," \"all done\" logs only after every item has been saved, in order",[115,2110,2112,2114,2115,2117],{"className":2111},[118],[120,2113],{"disabled":78,"type":122}," \"all done\" logs immediately, before any \"saved\" messages, because ",[32,2116,2035],{}," doesn't wait for the async callbacks it invokes",[115,2119,2121,2123,2124,2126],{"className":2120},[118],[120,2122],{"disabled":78,"type":122}," This throws, because ",[32,2125,2035],{}," doesn't accept async callbacks",[115,2128,2130,2132],{"className":2129},[118],[120,2131],{"disabled":78,"type":122}," Each iteration automatically awaits the previous one since they share the same array",[158,2134,2135,2137,2144],{},[161,2136,163],{},[165,2138,2139,2141,2142,2117],{},[168,2140,170],{}," B — \"all done\" logs immediately, before any \"saved\" messages, because ",[32,2143,2035],{},[165,2145,2146,141,2148,367,2150,2153,2154,2156,2157,2159,2160,2162,2163,2165,2166,2169,2170,2172,2173,2176],{},[168,2147,180],{},[168,2149,366],{},[32,2151,2152],{},"Array.prototype.forEach"," ignores whatever its callback returns, promise or not, and never awaits it — it just fires every callback invocation and moves straight on. Marking the callback ",[32,2155,42],{}," doesn't change that contract; it just means each call quietly starts its own promise chain in the background while ",[32,2158,2035],{}," itself barrels ahead. So ",[32,2161,2093],{}," logs before any ",[32,2164,1676],{}," line, and the saves may finish in arbitrary order. This is an extremely common real-world bug — use a ",[32,2167,2168],{},"for...of"," loop (Q13) for sequential awaiting or ",[32,2171,961],{}," with ",[32,2174,2175],{},"map"," (Q14) for parallel awaiting.",[14,2178,2179,2186,2265,2305],{"language":16},[18,2180,2182,2183,2185],{"id":2181},"q13-same-task-rewritten-with-forof","Q13. Same task, rewritten with ",[32,2184,2168],{},":",[23,2187,2188],{"language":16},[26,2189,2191],{"className":28,"code":2190,"language":16,"meta":30,"style":30},"async function processAll(items) {\n  for (const item of items) {\n    await saveItem(item);\n    console.log(\"saved\", item.id);\n  }\n  console.log(\"all done\");\n}\n",[32,2192,2193,2207,2225,2233,2245,2249,2261],{"__ignoreMap":30},[35,2194,2195,2197,2199,2201,2203,2205],{"class":37,"line":38},[35,2196,42],{"class":41},[35,2198,45],{"class":41},[35,2200,2020],{"class":48},[35,2202,241],{"class":52},[35,2204,2025],{"class":264},[35,2206,431],{"class":52},[35,2208,2209,2212,2214,2216,2219,2222],{"class":37,"line":56},[35,2210,2211],{"class":41},"  for",[35,2213,2042],{"class":52},[35,2215,85],{"class":41},[35,2217,2218],{"class":62}," item",[35,2220,2221],{"class":41}," of",[35,2223,2224],{"class":52}," items) {\n",[35,2226,2227,2229,2231],{"class":37,"line":69},[35,2228,2058],{"class":41},[35,2230,2061],{"class":48},[35,2232,2064],{"class":52},[35,2234,2235,2237,2239,2241,2243],{"class":37,"line":75},[35,2236,1312],{"class":52},[35,2238,105],{"class":48},[35,2240,241],{"class":52},[35,2242,1676],{"class":244},[35,2244,2077],{"class":52},[35,2246,2247],{"class":37,"line":82},[35,2248,506],{"class":52},[35,2250,2251,2253,2255,2257,2259],{"class":37,"line":99},[35,2252,236],{"class":52},[35,2254,105],{"class":48},[35,2256,241],{"class":52},[35,2258,2093],{"class":244},[35,2260,248],{"class":52},[35,2262,2263],{"class":37,"line":304},[35,2264,72],{"class":52},[110,2266,2268,2277,2288,2296],{"className":2267},[113],[115,2269,2271,2273,2274,2276],{"className":2270},[118],[120,2272],{"disabled":78,"type":122}," Behaves identically to the ",[32,2275,2035],{}," version in Q12",[115,2278,2280,2282,2283,2285,2286],{"className":2279},[118],[120,2281],{"disabled":78,"type":122}," This throws — ",[32,2284,2168],{}," bodies can't contain ",[32,2287,370],{},[115,2289,2291,2293,2294],{"className":2290},[118],[120,2292],{"disabled":78,"type":122}," Items save concurrently, the same as ",[32,2295,961],{},[115,2297,2299,2301,2302,2304],{"className":2298},[118],[120,2300],{"disabled":78,"type":122}," Each ",[32,2303,370],{}," genuinely pauses the loop until that item's save completes, so items save one at a time, in order, before \"all done\" logs",[158,2306,2307,2309,2316],{},[161,2308,163],{},[165,2310,2311,2313,2314,2304],{},[168,2312,170],{}," D — Each ",[32,2315,370],{},[165,2317,2318,141,2320,2322,2323,757,2325,2327,2328,2330,2331,2333,2334,2336,2337,2339,2340,2342],{},[168,2319,180],{},[168,2321,1227],{}," — Unlike ",[32,2324,2035],{},[32,2326,2168],{}," is ordinary synchronous control flow wrapped around each iteration; the ",[32,2329,370],{}," inside the loop body genuinely suspends the enclosing ",[32,2332,184],{}," until that iteration's promise settles before advancing. This makes ",[32,2335,2168],{}," the right tool when you need strictly sequential, ordered, one-at-a-time processing — reach for ",[32,2338,961],{}," + ",[32,2341,2175],{}," (Q14) instead when order doesn't matter and speed does.",[14,2344,2345,2349,2412,2450],{"language":16},[18,2346,2348],{"id":2347},"q14-same-task-again-this-time-written-as","Q14. Same task again, this time written as:",[23,2350,2351],{"language":16},[26,2352,2354],{"className":28,"code":2353,"language":16,"meta":30,"style":30},"async function processAll(items) {\n  await Promise.all(items.map(item => saveItem(item)));\n  console.log(\"all done\");\n}\n",[32,2355,2356,2370,2396,2408],{"__ignoreMap":30},[35,2357,2358,2360,2362,2364,2366,2368],{"class":37,"line":38},[35,2359,42],{"class":41},[35,2361,45],{"class":41},[35,2363,2020],{"class":48},[35,2365,241],{"class":52},[35,2367,2025],{"class":264},[35,2369,431],{"class":52},[35,2371,2372,2374,2376,2378,2380,2383,2385,2387,2389,2391,2393],{"class":37,"line":56},[35,2373,253],{"class":41},[35,2375,259],{"class":62},[35,2377,457],{"class":52},[35,2379,1157],{"class":48},[35,2381,2382],{"class":52},"(items.",[35,2384,2175],{"class":48},[35,2386,241],{"class":52},[35,2388,2045],{"class":264},[35,2390,268],{"class":41},[35,2392,2061],{"class":48},[35,2394,2395],{"class":52},"(item)));\n",[35,2397,2398,2400,2402,2404,2406],{"class":37,"line":69},[35,2399,236],{"class":52},[35,2401,105],{"class":48},[35,2403,241],{"class":52},[35,2405,2093],{"class":244},[35,2407,248],{"class":52},[35,2409,2410],{"class":37,"line":75},[35,2411,72],{"class":52},[110,2413,2415,2424,2432,2441],{"className":2414},[113],[115,2416,2418,2420,2421,2423],{"className":2417},[118],[120,2419],{"disabled":78,"type":122}," All ",[32,2422,1998],{}," calls start essentially simultaneously, and \"all done\" logs only once every one has settled successfully",[115,2425,2427,2429,2430,2276],{"className":2426},[118],[120,2428],{"disabled":78,"type":122}," This behaves exactly like the ",[32,2431,2035],{},[115,2433,2435,141,2437,2440],{"className":2434},[118],[120,2436],{"disabled":78,"type":122},[32,2438,2439],{},"items.map"," isn't allowed to return promises",[115,2442,2444,2446,2447,2449],{"className":2443},[118],[120,2445],{"disabled":78,"type":122}," Only the first ",[32,2448,1998],{}," call actually runs — the rest are discarded",[158,2451,2452,2454,2461],{},[161,2453,163],{},[165,2455,2456,2458,2459,2423],{},[168,2457,170],{}," A — All ",[32,2460,1998],{},[165,2462,2463,141,2465,2467,2468,367,2470,2473,2474,2476,2477,2480],{},[168,2464,180],{},[168,2466,942],{},"\u002F",[168,2469,1227],{},[32,2471,2472],{},"items.map(item => saveItem(item))"," synchronously invokes ",[32,2475,1998],{}," for every item up front, producing an array of promises; ",[32,2478,2479],{},"Promise.all(...)"," then awaits them all together, resolving only once every one has fulfilled (or rejecting fast on the first failure). This is the idiomatic way to process a collection concurrently when per-item ordering isn't required, and it directly fixes Q12's bug by actually awaiting the work instead of silently dropping it.",[14,2482,2483,2490,2526],{"language":16},[18,2484,2486,2487,2489],{"id":2485},"q15-in-an-es-module-a-top-level-await-that-takes-2-seconds-to-settle-will","Q15. In an ES module, a top-level ",[32,2488,370],{}," that takes 2 seconds to settle will...",[110,2491,2493,2499,2511,2520],{"className":2492},[113],[115,2494,2496,2498],{"className":2495},[118],[120,2497],{"disabled":78,"type":122}," Only delay code within that same module file — importing modules are unaffected",[115,2500,2502,2504,2505,2507,2508,2510],{"className":2501},[118],[120,2503],{"disabled":78,"type":122}," Cause a syntax error, since ",[32,2506,370],{}," is only legal inside ",[32,2509,42],{}," functions",[115,2512,2514,2516,2517,2519],{"className":2513},[118],[120,2515],{"disabled":78,"type":122}," Delay evaluation of the entire module, and any module that imports it will also wait for that evaluation (including the top-level ",[32,2518,370],{},") to finish before it can use the imports",[115,2521,2523,2525],{"className":2522},[118],[120,2524],{"disabled":78,"type":122}," Run in the background without blocking anything, since ESM loading is inherently async already",[158,2527,2528,2530,2537],{},[161,2529,163],{},[165,2531,2532,2534,2535,2519],{},[168,2533,170],{}," C — Delay evaluation of the entire module, and any module that imports it will also wait for that evaluation (including the top-level ",[32,2536,370],{},[165,2538,2539,141,2541,2467,2543,2545,2546,2548,2549,2552,2553,2555],{},[168,2540,180],{},[168,2542,366],{},[168,2544,942],{}," — Top-level ",[32,2547,370],{}," (ESM-only) pauses the ",[373,2550,2551],{},"evaluation of the containing module itself"," at that point until the awaited promise settles. Because the module graph is evaluated respecting dependency order, any module that imports the awaiting module must wait for it to fully finish evaluating — top-level ",[32,2554,370],{}," included — before the importer can proceed. This can cascade delays through an entire dependency graph, which is why it's best reserved for genuinely required async setup (like initializing a WASM module) rather than used casually.",[14,2557,2558,2573,2710,2761],{"language":16},[18,2559,2561,2562,2565,2566,2568,2569,2572],{"id":2560},"q16-getconfig-is-called-without-await-what-happens-if-key-is-falsy","Q16. ",[32,2563,2564],{},"getConfig"," is called without ",[32,2567,370],{},". What happens if ",[32,2570,2571],{},"key"," is falsy?",[23,2574,2575],{"language":16},[26,2576,2578],{"className":28,"code":2577,"language":16,"meta":30,"style":30},"const getConfig = async (key) => {\n  if (!key) {\n    throw new Error(\"key is required\");\n  }\n  return await loadFromDisk(key);\n};\n\ntry {\n  const result = getConfig();\n  console.log(result);\n} catch (err) {\n  console.log(\"caught:\", err.message);\n}\n",[32,2579,2580,2602,2615,2631,2635,2647,2652,2656,2662,2674,2682,2692,2705],{"__ignoreMap":30},[35,2581,2582,2584,2587,2589,2592,2594,2596,2598,2600],{"class":37,"line":38},[35,2583,85],{"class":41},[35,2585,2586],{"class":48}," getConfig",[35,2588,91],{"class":41},[35,2590,2591],{"class":41}," async",[35,2593,2042],{"class":52},[35,2595,2571],{"class":264},[35,2597,2048],{"class":52},[35,2599,2051],{"class":41},[35,2601,439],{"class":52},[35,2603,2604,2607,2609,2612],{"class":37,"line":56},[35,2605,2606],{"class":41},"  if",[35,2608,2042],{"class":52},[35,2610,2611],{"class":41},"!",[35,2613,2614],{"class":52},"key) {\n",[35,2616,2617,2620,2622,2624,2626,2629],{"class":37,"line":69},[35,2618,2619],{"class":41},"    throw",[35,2621,256],{"class":41},[35,2623,468],{"class":48},[35,2625,241],{"class":52},[35,2627,2628],{"class":244},"\"key is required\"",[35,2630,248],{"class":52},[35,2632,2633],{"class":37,"line":75},[35,2634,506],{"class":52},[35,2636,2637,2639,2641,2644],{"class":37,"line":82},[35,2638,59],{"class":41},[35,2640,452],{"class":41},[35,2642,2643],{"class":48}," loadFromDisk",[35,2645,2646],{"class":52},"(key);\n",[35,2648,2649],{"class":37,"line":99},[35,2650,2651],{"class":52},"};\n",[35,2653,2654],{"class":37,"line":304},[35,2655,79],{"emptyLinePlaceholder":78},[35,2657,2658,2660],{"class":37,"line":312},[35,2659,1369],{"class":41},[35,2661,439],{"class":52},[35,2663,2664,2666,2668,2670,2672],{"class":37,"line":513},[35,2665,686],{"class":41},[35,2667,88],{"class":62},[35,2669,91],{"class":41},[35,2671,2586],{"class":48},[35,2673,96],{"class":52},[35,2675,2676,2678,2680],{"class":37,"line":518},[35,2677,236],{"class":52},[35,2679,105],{"class":48},[35,2681,108],{"class":52},[35,2683,2685,2688,2690],{"class":37,"line":2684},11,[35,2686,2687],{"class":52},"} ",[35,2689,491],{"class":41},[35,2691,494],{"class":52},[35,2693,2695,2697,2699,2701,2703],{"class":37,"line":2694},12,[35,2696,236],{"class":52},[35,2698,105],{"class":48},[35,2700,241],{"class":52},[35,2702,1319],{"class":244},[35,2704,1322],{"class":52},[35,2706,2708],{"class":37,"line":2707},13,[35,2709,72],{"class":52},[110,2711,2713,2725,2737,2749],{"className":2712},[113],[115,2714,2716,141,2718,2721,2722,2724],{"className":2715},[118],[120,2717],{"disabled":78,"type":122},[32,2719,2720],{},"\"caught: key is required\""," logs, since ",[32,2723,596],{}," always produces a synchronous exception",[115,2726,2728,1547,2730,2732,2733,2736],{"className":2727},[118],[120,2729],{"disabled":78,"type":122},[32,2731,491],{}," block does NOT run — ",[32,2734,2735],{},"getConfig()"," returns a rejected promise instead, and the rejection goes unhandled",[115,2738,2740,2742,2743,2745,2746,2748],{"className":2739},[118],[120,2741],{"disabled":78,"type":122}," Both the ",[32,2744,1369],{}," block's log and the ",[32,2747,491],{}," block run",[115,2750,2752,128,2754,2757,2758,2760],{"className":2751},[118],[120,2753],{"disabled":78,"type":122},[32,2755,2756],{},"ReferenceError"," is thrown because ",[32,2759,2571],{}," is undefined",[158,2762,2763,2765,2774],{},[161,2764,163],{},[165,2766,2767,2769,2770,2732,2772,2736],{},[168,2768,170],{}," B — The ",[32,2771,491],{},[32,2773,2735],{},[165,2775,2776,141,2778,2780,2781,2783,2784,2786,2787,2789,2790,2792,2793,2795,2796,2799,2800,2802,2803,2805],{},[168,2777,180],{},[168,2779,366],{}," — Marking a function ",[32,2782,42],{}," changes what ",[32,2785,596],{}," does inside it: even a ",[32,2788,596],{}," that happens before any ",[32,2791,370],{}," never becomes a synchronous JS-engine exception at the call site — it's converted into a rejected promise returned by ",[32,2794,2735],{},". Since the caller doesn't ",[32,2797,2798],{},"await getConfig()",", the surrounding ",[32,2801,1418],{}," (which only sees synchronous throws and awaited rejections) never observes it, and the rejection surfaces later as unhandled. This trips up developers used to \"validate then ",[32,2804,596],{},"\" patterns in plain synchronous functions.",[14,2807,2808,2820,2864],{"language":16},[18,2809,2811,2812,2815,2816,2819],{"id":2810},"q17-which-statement-correctly-describes-async-function-combined-with-for-awaitof","Q17. Which statement correctly describes ",[32,2813,2814],{},"async function*"," combined with ",[32,2817,2818],{},"for await...of","?",[110,2821,2823,2835,2841,2851],{"className":2822},[113],[115,2824,2826,2828,2829,2831,2832,2834],{"className":2825},[118],[120,2827],{"disabled":78,"type":122}," It's identical to a regular generator; ",[32,2830,2818],{}," is just syntax sugar for ",[32,2833,2168],{}," with no behavioral difference",[115,2836,2838,2840],{"className":2837},[118],[120,2839],{"disabled":78,"type":122}," Async generators can only be used with arrays, not streams or async iterables",[115,2842,2844,141,2846,2848,2849],{"className":2843},[118],[120,2845],{"disabled":78,"type":122},[32,2847,2818],{}," requires all values to be available synchronously upfront, unlike ",[32,2850,2168],{},[115,2852,2854,2856,2857,2860,2861,2863],{"className":2853},[118],[120,2855],{"disabled":78,"type":122}," An async generator's ",[32,2858,2859],{},"yield"," can produce values that are themselves promises (or come from awaited async work), and ",[32,2862,2818],{}," automatically awaits each yielded value before running the loop body",[158,2865,2866,2868,2877],{},[161,2867,163],{},[165,2869,2870,2872,2873,2860,2875,2863],{},[168,2871,170],{}," D — An async generator's ",[32,2874,2859],{},[32,2876,2818],{},[165,2878,2879,181,2881,2883,2884,2886,2887,2889],{},[168,2880,180],{},[32,2882,2814],{}," produces an async iterator; ",[32,2885,2818],{}," consumes it by awaiting each yielded item automatically, one at a time. This makes it a natural fit for representing sequences of values that arrive over time — paginated API results, or chunks read from a stream — which a plain generator plus ",[32,2888,2168],{}," can't express since those only handle synchronous iteration. Options A, B, and C each misstate that relationship.",[14,2891,2892,2896,2959,3013],{"language":16},[18,2893,2895],{"id":2894},"q18-is-this-code-valid-and-is-it-good-style","Q18. Is this code valid, and is it good style?",[23,2897,2898],{"language":16},[26,2899,2901],{"className":28,"code":2900,"language":16,"meta":30,"style":30},"async function loadProfile(id) {\n  const user = await fetchUser(id);\n  return fetchPosts(user.id).then(posts => ({ user, posts }));\n}\n",[32,2902,2903,2918,2933,2955],{"__ignoreMap":30},[35,2904,2905,2907,2909,2912,2914,2916],{"class":37,"line":38},[35,2906,42],{"class":41},[35,2908,45],{"class":41},[35,2910,2911],{"class":48}," loadProfile",[35,2913,241],{"class":52},[35,2915,428],{"class":264},[35,2917,431],{"class":52},[35,2919,2920,2922,2924,2926,2928,2930],{"class":37,"line":56},[35,2921,686],{"class":41},[35,2923,864],{"class":62},[35,2925,91],{"class":41},[35,2927,452],{"class":41},[35,2929,423],{"class":48},[35,2931,2932],{"class":52},"(id);\n",[35,2934,2935,2937,2940,2943,2945,2947,2950,2952],{"class":37,"line":69},[35,2936,59],{"class":41},[35,2938,2939],{"class":48}," fetchPosts",[35,2941,2942],{"class":52},"(user.id).",[35,2944,532],{"class":48},[35,2946,241],{"class":52},[35,2948,2949],{"class":264},"posts",[35,2951,268],{"class":41},[35,2953,2954],{"class":52}," ({ user, posts }));\n",[35,2956,2957],{"class":37,"line":75},[35,2958,72],{"class":52},[110,2960,2962,2974,2987,2999],{"className":2961},[113],[115,2963,2965,2967,2968,835,2970,2973],{"className":2964},[118],[120,2966],{"disabled":78,"type":122}," It's valid, but mixing ",[32,2969,370],{},[32,2971,2972],{},".then()"," chains in the same function is generally considered inconsistent style — sticking to one approach throughout improves readability",[115,2975,2977,2979,2980,787,2982,2984,2985],{"className":2976},[118],[120,2978],{"disabled":78,"type":122}," It throws a syntax error — you can't ",[32,2981,786],{},[32,2983,2972],{}," chain from an ",[32,2986,184],{},[115,2988,2990,141,2992,2995,2996,2998],{"className":2989},[118],[120,2991],{"disabled":78,"type":122},[32,2993,2994],{},"fetchPosts(user.id).then(...)"," runs synchronously before ",[32,2997,521],{}," resolves",[115,3000,3002,1547,3004,3006,3007,3010,3011],{"className":3001},[118],[120,3003],{"disabled":78,"type":122},[32,3005,2972],{}," chain's returned promise is discarded — ",[32,3008,3009],{},"loadProfile"," always resolves to ",[32,3012,144],{},[158,3014,3015,3017,3026],{},[161,3016,163],{},[165,3018,3019,3021,3022,835,3024,2973],{},[168,3020,170],{}," A — It's valid, but mixing ",[32,3023,370],{},[32,3025,2972],{},[165,3027,3028,141,3030,3032,3033,2172,3035,2467,3037,3040,3041,3043,3044,3046,3047,3050],{},[168,3029,180],{},[168,3031,1227],{}," — Nothing here is actually broken: async functions can freely mix ",[32,3034,370],{},[32,3036,2972],{},[32,3038,3039],{},".catch()"," chains, and the promise returned by ",[32,3042,2972],{}," is flattened into ",[32,3045,3009],{},"'s own return value, same as Q4. The issue is purely readability\u002Fconsistency — switching styles mid-function makes control flow harder to scan. The idiomatic fix is ",[32,3048,3049],{},"const posts = await fetchPosts(user.id); return { user, posts };",", keeping the whole function in one style.",[14,3052,3053,3057,3137,3177],{"language":16},[18,3054,3056],{"id":3055},"q19-what-order-do-the-logs-print-in","Q19. What order do the logs print in?",[23,3058,3059],{"language":16},[26,3060,3062],{"className":28,"code":3061,"language":16,"meta":30,"style":30},"async function test() {\n  console.log(\"1\");\n  await 42;\n  console.log(\"2\");\n}\n\ntest();\nconsole.log(\"3\");\n",[32,3063,3064,3075,3088,3096,3109,3113,3117,3124],{"__ignoreMap":30},[35,3065,3066,3068,3070,3073],{"class":37,"line":38},[35,3067,42],{"class":41},[35,3069,45],{"class":41},[35,3071,3072],{"class":48}," test",[35,3074,53],{"class":52},[35,3076,3077,3079,3081,3083,3086],{"class":37,"line":56},[35,3078,236],{"class":52},[35,3080,105],{"class":48},[35,3082,241],{"class":52},[35,3084,3085],{"class":244},"\"1\"",[35,3087,248],{"class":52},[35,3089,3090,3092,3094],{"class":37,"line":69},[35,3091,253],{"class":41},[35,3093,63],{"class":62},[35,3095,66],{"class":52},[35,3097,3098,3100,3102,3104,3107],{"class":37,"line":75},[35,3099,236],{"class":52},[35,3101,105],{"class":48},[35,3103,241],{"class":52},[35,3105,3106],{"class":244},"\"2\"",[35,3108,248],{"class":52},[35,3110,3111],{"class":37,"line":82},[35,3112,72],{"class":52},[35,3114,3115],{"class":37,"line":99},[35,3116,79],{"emptyLinePlaceholder":78},[35,3118,3119,3122],{"class":37,"line":304},[35,3120,3121],{"class":48},"test",[35,3123,96],{"class":52},[35,3125,3126,3128,3130,3132,3135],{"class":37,"line":312},[35,3127,102],{"class":52},[35,3129,105],{"class":48},[35,3131,241],{"class":52},[35,3133,3134],{"class":244},"\"3\"",[35,3136,248],{"class":52},[110,3138,3140,3149,3155,3161],{"className":3139},[113],[115,3141,3143,3145,3146,3148],{"className":3142},[118],[120,3144],{"disabled":78,"type":122}," 1, 2, 3 — awaiting a plain value like ",[32,3147,135],{}," doesn't actually pause anything",[115,3150,3152,3154],{"className":3151},[118],[120,3153],{"disabled":78,"type":122}," 3, 1, 2 — the whole async function is deferred until the synchronous code finishes",[115,3156,3158,3160],{"className":3157},[118],[120,3159],{"disabled":78,"type":122}," 1, 3, 2 — awaiting any value, even a non-promise, always yields to the microtask queue before resuming",[115,3162,3164,3166,3167,3170,3171,3173,3174,3176],{"className":3163},[118],[120,3165],{"disabled":78,"type":122}," This throws a ",[32,3168,3169],{},"TypeError"," — you can only ",[32,3172,370],{}," actual ",[32,3175,131],{}," objects",[158,3178,3179,3181,3186],{},[161,3180,163],{},[165,3182,3183,3185],{},[168,3184,170],{}," C — 1, 3, 2 — awaiting any value, even a non-promise, always yields to the microtask queue before resuming",[165,3187,3188,141,3190,2467,3192,367,3194,3196,3197,3200,3201,3204,3205,3207,3208,3211,3212,3214,3215,3217],{},[168,3189,180],{},[168,3191,366],{},[168,3193,942],{},[32,3195,370],{}," always suspends the async function and schedules its resumption as a microtask, even when the awaited value isn't a thenable at all — the engine internally treats it as ",[32,3198,3199],{},"Promise.resolve(42)",". So ",[32,3202,3203],{},"test()"," logs ",[32,3206,3085],{},", then immediately yields back to the caller; ",[32,3209,3210],{},"console.log(\"3\")"," runs next synchronously; only then does the microtask queue drain and ",[32,3213,3106],{}," logs. This surprises people who assume \"no real async work happening, so no delay\" — even a trivial ",[32,3216,370],{}," costs at least one microtask tick.",[14,3219,3220,3224,3260],{"language":16},[18,3221,3223],{"id":3222},"q20-a-function-needs-a-users-profile-their-settings-and-their-notification-count-three-independent-api-calls-that-dont-depend-on-each-others-results-combined-into-one-object-which-approach-is-best-practice","Q20. A function needs a user's profile, their settings, and their notification count — three independent API calls that don't depend on each other's results — combined into one object. Which approach is best practice?",[110,3225,3227,3233,3242,3251],{"className":3226},[113],[115,3228,3230,3232],{"className":3229},[118],[120,3231],{"disabled":78,"type":122}," Await each call sequentially, one after another, for the clearest, most linear-reading code",[115,3234,3236,3238,3239,3241],{"className":3235},[118],[120,3237],{"disabled":78,"type":122}," Use ",[32,3240,2972],{}," chains for each call, since async\u002Fawait can't combine multiple independent results",[115,3243,3245,3247,3248,3250],{"className":3244},[118],[120,3246],{"disabled":78,"type":122}," Wrap each call in its own ",[32,3249,1418],{}," and await them one at a time so errors stay isolated per call",[115,3252,3254,3256,3257,3259],{"className":3253},[118],[120,3255],{"disabled":78,"type":122}," Kick off all three calls without awaiting immediately (or use ",[32,3258,961],{},"), then await them together, since running independent operations concurrently minimizes total wait time",[158,3261,3262,3264,3271],{},[161,3263,163],{},[165,3265,3266,3268,3269,3259],{},[168,3267,170],{}," D — Kick off all three calls without awaiting immediately (or use ",[32,3270,961],{},[165,3272,3273,141,3275,2467,3277,3279,3280,3283,3284,3286,3287,3289],{},[168,3274,180],{},[168,3276,942],{},[168,3278,1227],{}," — When operations don't depend on each other, best practice is to start them concurrently — either call all three functions first and await the results afterward, or more idiomatically write ",[32,3281,3282],{},"const [profile, settings, count] = await Promise.all([...])"," — so total latency is bounded by the slowest call rather than their sum, avoiding Q5's footgun. Option A is the common but suboptimal sequential pattern; option C still serializes the calls despite sounding \"safer\" — per-call isolation with ",[32,3285,1418],{}," isn't required for independent operations (use ",[32,3288,1243],{}," instead if partial-failure tolerance is genuinely needed).",[3291,3292,3293],"style",{},"html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":30,"searchDepth":56,"depth":56,"links":3295},[3296,3297,3298,3300,3301,3303,3304,3305,3307,3309,3311,3313,3315,3317,3318,3320,3322,3324,3325,3326],{"id":20,"depth":69,"text":21},{"id":212,"depth":69,"text":213},{"id":402,"depth":69,"text":3299},"Q3. What does fetchUser(1).then(console.log) print?",{"id":626,"depth":69,"text":627},{"id":830,"depth":69,"text":3302},"Q5. fetchUser() and fetchStats() are independent — neither depends on the other's result, and each takes ~300ms.",{"id":967,"depth":69,"text":968},{"id":1109,"depth":69,"text":1110},{"id":1249,"depth":69,"text":3306},"Q8. riskyOperation() returns a promise that may reject. What happens if it does?",{"id":1450,"depth":69,"text":3308},"Q9. Now the await has moved inside the try block, even though riskyOperation() is still called before it:",{"id":1618,"depth":69,"text":3310},"Q10. saveUser is async. What order do the logs print in when handleSubmit(user) runs?",{"id":1816,"depth":69,"text":3312},"Q11. saveUser is async and may reject internally. What happens when it does?",{"id":1994,"depth":69,"text":3314},"Q12. saveItem is async. What happens when processAll runs?",{"id":2181,"depth":69,"text":3316},"Q13. Same task, rewritten with for...of:",{"id":2347,"depth":69,"text":2348},{"id":2485,"depth":69,"text":3319},"Q15. In an ES module, a top-level await that takes 2 seconds to settle will...",{"id":2560,"depth":69,"text":3321},"Q16. getConfig is called without await. What happens if key is falsy?",{"id":2810,"depth":69,"text":3323},"Q17. Which statement correctly describes async function* combined with for await...of?",{"id":2894,"depth":69,"text":2895},{"id":3055,"depth":69,"text":3056},{"id":3222,"depth":69,"text":3223},"md",{},"\u002Fjs\u002F17-async-await",{"title":5,"description":30},"js\u002F17-async-await","mqHkR68FB6kb6wQpbIEU99eTuBuUjLmFTdhHFlnY7uY",1787335397335]