[{"data":1,"prerenderedAt":3853},["ShallowReactive",2],{"page-\u002Fjs\u002F18-error-handling":3},{"id":4,"title":5,"body":6,"description":187,"extension":3847,"meta":3848,"navigation":43,"path":3849,"seo":3850,"stem":3851,"__hash__":3852},"content\u002Fjs\u002F18-error-handling.md","18 — Error Handling",{"type":7,"value":8,"toc":3819},"minimark",[9,13,172,365,553,772,1027,1204,1364,1615,1822,2069,2299,2506,2722,2877,2944,3129,3334,3391,3615,3815],[10,11,5],"h1",{"id":12},"_18-error-handling",[14,15,16,30,99],"question-wrapper",{},[17,18,20,21,25,26,29],"h3",{"id":19},"q1-which-statement-about-the-finally-block-in-a-trycatchfinally-statement-is-true","Q1. Which statement about the ",[22,23,24],"code",{},"finally"," block in a ",[22,27,28],{},"try\u002Fcatch\u002Ffinally"," statement is true?",[31,32,35,53,77,88],"ul",{"className":33},[34],"contains-task-list",[36,37,40,45,46,48,49,52],"li",{"className":38},[39],"task-list-item",[41,42],"input",{"disabled":43,"type":44},true,"checkbox"," ",[22,47,24],{}," only runs if the ",[22,50,51],{},"try"," block completes without throwing",[36,54,56,45,58,60,61,63,64,67,68,70,71,73,74],{"className":55},[39],[41,57],{"disabled":43,"type":44},[22,59,24],{}," runs after every ",[22,62,51],{},"\u002F",[22,65,66],{},"catch"," path, including when ",[22,69,51],{}," or ",[22,72,66],{}," contains a ",[22,75,76],{},"return",[36,78,80,45,82,84,85,87],{"className":79},[39],[41,81],{"disabled":43,"type":44},[22,83,24],{}," is skipped if the ",[22,86,66],{}," block itself throws a new error",[36,89,91,45,93,95,96,98],{"className":90},[39],[41,92],{"disabled":43,"type":44},[22,94,24],{}," only runs when there is no ",[22,97,66],{}," block present",[100,101,102,106,126],"details",{},[103,104,105],"summary",{},"Show Answer",[107,108,109,113,114,60,116,63,118,67,120,70,122,73,124],"p",{},[110,111,112],"strong",{},"Answer:"," B — ",[22,115,24],{},[22,117,51],{},[22,119,66],{},[22,121,51],{},[22,123,66],{},[22,125,76],{},[107,127,128,45,131,133,134,63,136,138,139,141,142,145,146,63,149,152,153,155,156,158,159,161,162,165,166,168,169,171],{},[110,129,130],{},"Explanation:",[22,132,24],{}," always executes regardless of how ",[22,135,51],{},[22,137,66],{}," exits — normal completion, ",[22,140,76],{},", ",[22,143,144],{},"throw",", or even ",[22,147,148],{},"break",[22,150,151],{},"continue",". Even if ",[22,154,66],{}," throws a new error, ",[22,157,24],{}," still runs before that error propagates further, which rules out C. A is wrong because ",[22,160,24],{}," runs on both success and failure paths, not just success. D is wrong because ",[22,163,164],{},"try\u002Ffinally"," (with no ",[22,167,66],{}," at all) is perfectly valid, and ",[22,170,24],{}," still runs.",[14,173,175,179,285,319],{"language":174},"javascript",[17,176,178],{"id":177},"q2-what-does-this-log","Q2. What does this log?",[180,181,182],"code-wrapper",{"language":174},[183,184,188],"pre",{"className":185,"code":186,"language":174,"meta":187,"style":187},"language-javascript shiki shiki-themes github-light github-dark","function getStatus() {\n  try {\n    return \"success\";\n  } finally {\n    return \"overridden\";\n  }\n}\n\nconsole.log(getStatus());\n","",[22,189,190,207,216,229,239,249,255,261,267],{"__ignoreMap":187},[191,192,195,199,203],"span",{"class":193,"line":194},"line",1,[191,196,198],{"class":197},"svdQ7","function",[191,200,202],{"class":201},"sIsaT"," getStatus",[191,204,206],{"class":205},"ssxIu","() {\n",[191,208,210,213],{"class":193,"line":209},2,[191,211,212],{"class":197},"  try",[191,214,215],{"class":205}," {\n",[191,217,219,222,226],{"class":193,"line":218},3,[191,220,221],{"class":197},"    return",[191,223,225],{"class":224},"sJ6F3"," \"success\"",[191,227,228],{"class":205},";\n",[191,230,232,235,237],{"class":193,"line":231},4,[191,233,234],{"class":205},"  } ",[191,236,24],{"class":197},[191,238,215],{"class":205},[191,240,242,244,247],{"class":193,"line":241},5,[191,243,221],{"class":197},[191,245,246],{"class":224}," \"overridden\"",[191,248,228],{"class":205},[191,250,252],{"class":193,"line":251},6,[191,253,254],{"class":205},"  }\n",[191,256,258],{"class":193,"line":257},7,[191,259,260],{"class":205},"}\n",[191,262,264],{"class":193,"line":263},8,[191,265,266],{"emptyLinePlaceholder":43},"\n",[191,268,270,273,276,279,282],{"class":193,"line":269},9,[191,271,272],{"class":205},"console.",[191,274,275],{"class":201},"log",[191,277,278],{"class":205},"(",[191,280,281],{"class":201},"getStatus",[191,283,284],{"class":205},"());\n",[31,286,288,293,301,314],{"className":287},[34],[36,289,291,225],{"className":290},[39],[41,292],{"disabled":43,"type":44},[36,294,296,45,298],{"className":295},[39],[41,297],{"disabled":43,"type":44},[22,299,300],{},"undefined",[36,302,304,306,307,310,311,313],{"className":303},[39],[41,305],{"disabled":43,"type":44}," A ",[22,308,309],{},"SyntaxError"," is thrown because you cannot ",[22,312,76],{}," twice in one function",[36,315,317,246],{"className":316},[39],[41,318],{"disabled":43,"type":44},[100,320,321,323,328],{},[103,322,105],{},[107,324,325,327],{},[110,326,112],{}," D — \"overridden\"",[107,329,330,306,332,334,335,337,338,340,341,344,345,347,348,351,352,355,356,358,359,361,362],{},[110,331,130],{},[22,333,76],{}," inside ",[22,336,24],{}," silently overrides the pending return value from ",[22,339,51],{},". The engine has already set up ",[22,342,343],{},"\"success\""," as the function's about-to-be-returned value, but before control actually leaves the function, ",[22,346,24],{}," runs — and its own ",[22,349,350],{},"return \"overridden\""," replaces that pending value entirely. No error is thrown; this is legal but dangerous JavaScript (ESLint's ",[22,353,354],{},"no-unsafe-finally"," rule exists specifically to flag it). A is the intuitive-but-wrong guess that ",[22,357,51],{},"'s ",[22,360,76],{}," should win. ",[110,363,364],{},"Debug",[14,366,367,371,454,499],{"language":174},[17,368,370],{"id":369},"q3-what-does-this-log","Q3. What does this log?",[180,372,373],{"language":174},[183,374,376],{"className":185,"code":375,"language":174,"meta":187,"style":187},"function loadConfig() {\n  try {\n    throw new Error(\"config missing\");\n  } finally {\n    return \"default-config\";\n  }\n}\n\nconsole.log(loadConfig());\n",[22,377,378,387,393,412,420,429,433,437,441],{"__ignoreMap":187},[191,379,380,382,385],{"class":193,"line":194},[191,381,198],{"class":197},[191,383,384],{"class":201}," loadConfig",[191,386,206],{"class":205},[191,388,389,391],{"class":193,"line":209},[191,390,212],{"class":197},[191,392,215],{"class":205},[191,394,395,398,401,404,406,409],{"class":193,"line":218},[191,396,397],{"class":197},"    throw",[191,399,400],{"class":197}," new",[191,402,403],{"class":201}," Error",[191,405,278],{"class":205},[191,407,408],{"class":224},"\"config missing\"",[191,410,411],{"class":205},");\n",[191,413,414,416,418],{"class":193,"line":231},[191,415,234],{"class":205},[191,417,24],{"class":197},[191,419,215],{"class":205},[191,421,422,424,427],{"class":193,"line":241},[191,423,221],{"class":197},[191,425,426],{"class":224}," \"default-config\"",[191,428,228],{"class":205},[191,430,431],{"class":193,"line":251},[191,432,254],{"class":205},[191,434,435],{"class":193,"line":257},[191,436,260],{"class":205},[191,438,439],{"class":193,"line":263},[191,440,266],{"emptyLinePlaceholder":43},[191,442,443,445,447,449,452],{"class":193,"line":269},[191,444,272],{"class":205},[191,446,275],{"class":201},[191,448,278],{"class":205},[191,450,451],{"class":201},"loadConfig",[191,453,284],{"class":205},[31,455,457,463,473,479],{"className":456},[34],[36,458,460,462],{"className":459},[39],[41,461],{"disabled":43,"type":44}," \"default-config\" is logged, and the thrown error is completely swallowed",[36,464,466,468,469,472],{"className":465},[39],[41,467],{"disabled":43,"type":44}," The function throws \"config missing\" and the ",[22,470,471],{},"console.log"," line never runs",[36,474,476,478],{"className":475},[39],[41,477],{"disabled":43,"type":44}," Both the error message and the return value are logged",[36,480,482,306,484,487,488,490,491,493,494,496,497],{"className":481},[39],[41,483],{"disabled":43,"type":44},[22,485,486],{},"TypeError"," is thrown because ",[22,489,24],{}," cannot contain a ",[22,492,76],{}," after a ",[22,495,144],{}," in ",[22,498,51],{},[100,500,501,503,508],{},[103,502,105],{},[107,504,505,507],{},[110,506,112],{}," A — \"default-config\" is logged, and the thrown error is completely swallowed",[107,509,510,512,513,515,516,334,518,520,521,525,526,496,529,531,532,358,534,537,538,63,540,63,542,334,544,546,547,549,550],{},[110,511,130],{}," Just like it overrides a pending ",[22,514,76],{},", a ",[22,517,76],{},[22,519,24],{}," also overrides a pending ",[522,523,524],"em",{},"exception",". The ",[22,527,528],{},"throw new Error(\"config missing\")",[22,530,51],{}," never propagates because ",[22,533,24],{},[22,535,536],{},"return \"default-config\""," becomes the completion value of the whole statement instead. This silently discards a real error with no trace it ever happened — a genuinely dangerous pattern, which is why linters flag ",[22,539,76],{},[22,541,148],{},[22,543,151],{},[22,545,24],{},". ",[110,548,364],{}," \u002F ",[110,551,552],{},"Safety",[14,554,555,559,666,726],{"language":174},[17,556,558],{"id":557},"q4-what-happens-when-this-runs","Q4. What happens when this runs?",[180,560,561],{"language":174},[183,562,564],{"className":185,"code":563,"language":174,"meta":187,"style":187},"class ApiError extends Error {\n  constructor(message, statusCode) {\n    this.statusCode = statusCode;\n    this.message = message;\n  }\n}\n\nconst err = new ApiError(\"Not Found\", 404);\n",[22,565,566,581,600,615,627,631,635,639],{"__ignoreMap":187},[191,567,568,571,574,577,579],{"class":193,"line":194},[191,569,570],{"class":197},"class",[191,572,573],{"class":201}," ApiError",[191,575,576],{"class":197}," extends",[191,578,403],{"class":201},[191,580,215],{"class":205},[191,582,583,586,588,592,594,597],{"class":193,"line":209},[191,584,585],{"class":197},"  constructor",[191,587,278],{"class":205},[191,589,591],{"class":590},"sCrzJ","message",[191,593,141],{"class":205},[191,595,596],{"class":590},"statusCode",[191,598,599],{"class":205},") {\n",[191,601,602,606,609,612],{"class":193,"line":218},[191,603,605],{"class":604},"snvgF","    this",[191,607,608],{"class":205},".statusCode ",[191,610,611],{"class":197},"=",[191,613,614],{"class":205}," statusCode;\n",[191,616,617,619,622,624],{"class":193,"line":231},[191,618,605],{"class":604},[191,620,621],{"class":205},".message ",[191,623,611],{"class":197},[191,625,626],{"class":205}," message;\n",[191,628,629],{"class":193,"line":241},[191,630,254],{"class":205},[191,632,633],{"class":193,"line":251},[191,634,260],{"class":205},[191,636,637],{"class":193,"line":257},[191,638,266],{"emptyLinePlaceholder":43},[191,640,641,644,647,650,652,654,656,659,661,664],{"class":193,"line":263},[191,642,643],{"class":197},"const",[191,645,646],{"class":604}," err",[191,648,649],{"class":197}," =",[191,651,400],{"class":197},[191,653,573],{"class":201},[191,655,278],{"class":205},[191,657,658],{"class":224},"\"Not Found\"",[191,660,141],{"class":205},[191,662,663],{"class":604},"404",[191,665,411],{"class":205},[31,667,669,682,697,713],{"className":668},[34],[36,670,672,45,674,677,678,681],{"className":671},[39],[41,673],{"disabled":43,"type":44},[22,675,676],{},"err"," is created successfully and ",[22,679,680],{},"err.message"," is \"Not Found\"",[36,683,685,45,687,689,690,693,694],{"className":684},[39],[41,686],{"disabled":43,"type":44},[22,688,676],{}," is created but ",[22,691,692],{},"err instanceof Error"," is ",[22,695,696],{},"false",[36,698,700,306,702,487,705,708,709,712],{"className":699},[39],[41,701],{"disabled":43,"type":44},[22,703,704],{},"ReferenceError",[22,706,707],{},"this"," is accessed before ",[22,710,711],{},"super()"," is called",[36,714,716,45,718,693,721,723,724],{"className":715},[39],[41,717],{"disabled":43,"type":44},[22,719,720],{},"err.statusCode",[22,722,300],{}," because it was set before ",[22,725,591],{},[100,727,728,730,741],{},[103,729,105],{},[107,731,732,734,735,487,737,708,739,712],{},[110,733,112],{}," C — A ",[22,736,704],{},[22,738,707],{},[22,740,711],{},[107,742,743,745,746,748,749,751,752,755,756,758,759,762,763,765,766,769,770],{},[110,744,130],{}," In a derived class, ",[22,747,707],{}," is not initialized until ",[22,750,711],{}," runs. Writing ",[22,753,754],{},"this.statusCode = statusCode"," before calling ",[22,757,711],{}," throws \"Must call super constructor in derived class before accessing 'this' or returning from derived constructor.\" The fix is ",[22,760,761],{},"super(message)"," first, then assign any extra custom fields like ",[22,764,596],{},". A is the outcome you'd get ",[522,767,768],{},"after"," fixing the bug, not what actually happens here. ",[110,771,552],{},[14,773,774,778,940,988],{"language":174},[17,775,777],{"id":776},"q5-what-does-this-log","Q5. What does this log?",[180,779,780],{"language":174},[183,781,783],{"className":185,"code":782,"language":174,"meta":187,"style":187},"class AppError extends Error {}\nclass ValidationError extends AppError {}\n\nfunction validate(input) {\n  if (!input) throw new ValidationError(\"input required\");\n}\n\ntry {\n  validate(null);\n} catch (err) {\n  if (err instanceof AppError) {\n    console.log(\"handled:\", err instanceof ValidationError);\n  }\n}\n",[22,784,785,799,812,816,829,856,860,864,870,882,893,908,930,935],{"__ignoreMap":187},[191,786,787,789,792,794,796],{"class":193,"line":194},[191,788,570],{"class":197},[191,790,791],{"class":201}," AppError",[191,793,576],{"class":197},[191,795,403],{"class":201},[191,797,798],{"class":205}," {}\n",[191,800,801,803,806,808,810],{"class":193,"line":209},[191,802,570],{"class":197},[191,804,805],{"class":201}," ValidationError",[191,807,576],{"class":197},[191,809,791],{"class":201},[191,811,798],{"class":205},[191,813,814],{"class":193,"line":218},[191,815,266],{"emptyLinePlaceholder":43},[191,817,818,820,823,825,827],{"class":193,"line":231},[191,819,198],{"class":197},[191,821,822],{"class":201}," validate",[191,824,278],{"class":205},[191,826,41],{"class":590},[191,828,599],{"class":205},[191,830,831,834,837,840,843,845,847,849,851,854],{"class":193,"line":241},[191,832,833],{"class":197},"  if",[191,835,836],{"class":205}," (",[191,838,839],{"class":197},"!",[191,841,842],{"class":205},"input) ",[191,844,144],{"class":197},[191,846,400],{"class":197},[191,848,805],{"class":201},[191,850,278],{"class":205},[191,852,853],{"class":224},"\"input required\"",[191,855,411],{"class":205},[191,857,858],{"class":193,"line":251},[191,859,260],{"class":205},[191,861,862],{"class":193,"line":257},[191,863,266],{"emptyLinePlaceholder":43},[191,865,866,868],{"class":193,"line":263},[191,867,51],{"class":197},[191,869,215],{"class":205},[191,871,872,875,877,880],{"class":193,"line":269},[191,873,874],{"class":201},"  validate",[191,876,278],{"class":205},[191,878,879],{"class":604},"null",[191,881,411],{"class":205},[191,883,885,888,890],{"class":193,"line":884},10,[191,886,887],{"class":205},"} ",[191,889,66],{"class":197},[191,891,892],{"class":205}," (err) {\n",[191,894,896,898,901,904,906],{"class":193,"line":895},11,[191,897,833],{"class":197},[191,899,900],{"class":205}," (err ",[191,902,903],{"class":197},"instanceof",[191,905,791],{"class":201},[191,907,599],{"class":205},[191,909,911,914,916,918,921,924,926,928],{"class":193,"line":910},12,[191,912,913],{"class":205},"    console.",[191,915,275],{"class":201},[191,917,278],{"class":205},[191,919,920],{"class":224},"\"handled:\"",[191,922,923],{"class":205},", err ",[191,925,903],{"class":197},[191,927,805],{"class":201},[191,929,411],{"class":205},[191,931,933],{"class":193,"line":932},13,[191,934,254],{"class":205},[191,936,938],{"class":193,"line":937},14,[191,939,260],{"class":205},[31,941,943,956,965,974],{"className":942},[34],[36,944,946,948,949,952,953],{"className":945},[39],[41,947],{"disabled":43,"type":44}," Nothing is logged because ",[22,950,951],{},"ValidationError"," does not match ",[22,954,955],{},"AppError",[36,957,959,961,962,964],{"className":958},[39],[41,960],{"disabled":43,"type":44}," \"handled: true\", because ",[22,963,903],{}," walks the entire prototype chain",[36,966,968,970,971,973],{"className":967},[39],[41,969],{"disabled":43,"type":44}," \"handled: false\", because ",[22,972,903],{}," only checks the direct class",[36,975,977,306,979,981,982,984,985],{"className":976},[39],[41,978],{"disabled":43,"type":44},[22,980,486],{}," is thrown since you cannot ",[22,983,144],{}," a subclass of a subclass of ",[22,986,987],{},"Error",[100,989,990,992,999],{},[103,991,105],{},[107,993,994,996,997,964],{},[110,995,112],{}," B — \"handled: true\", because ",[22,998,903],{},[107,1000,1001,45,1003,1005,1006,1008,1009,1012,1013,1016,1017,1020,1021,1023,1024,1026],{},[110,1002,130],{},[22,1004,903],{}," checks the full prototype chain, not just the exact constructor. A ",[22,1007,951],{}," instance is also an ",[22,1010,1011],{},"instanceof AppError"," and an ",[22,1014,1015],{},"instanceof Error",", so both checks in the snippet are ",[22,1018,1019],{},"true",". This lets a broad ",[22,1022,903],{}," check higher up a hierarchy catch a whole family of related errors while still allowing narrower checks. C describes a common misconception that ",[22,1025,903],{}," only matches the exact class it was constructed with.",[14,1028,1029,1033,1117,1153],{"language":174},[17,1030,1032],{"id":1031},"q6-what-does-this-log","Q6. What does this log?",[180,1034,1035],{"language":174},[183,1036,1038],{"className":185,"code":1037,"language":174,"meta":187,"style":187},"class TimeoutError extends Error {\n  constructor(message) {\n    super(message);\n  }\n}\n\nconst err = new TimeoutError(\"request timed out\");\nconsole.log(err.name, err instanceof TimeoutError);\n",[22,1039,1040,1053,1063,1071,1075,1079,1083,1102],{"__ignoreMap":187},[191,1041,1042,1044,1047,1049,1051],{"class":193,"line":194},[191,1043,570],{"class":197},[191,1045,1046],{"class":201}," TimeoutError",[191,1048,576],{"class":197},[191,1050,403],{"class":201},[191,1052,215],{"class":205},[191,1054,1055,1057,1059,1061],{"class":193,"line":209},[191,1056,585],{"class":197},[191,1058,278],{"class":205},[191,1060,591],{"class":590},[191,1062,599],{"class":205},[191,1064,1065,1068],{"class":193,"line":218},[191,1066,1067],{"class":604},"    super",[191,1069,1070],{"class":205},"(message);\n",[191,1072,1073],{"class":193,"line":231},[191,1074,254],{"class":205},[191,1076,1077],{"class":193,"line":241},[191,1078,260],{"class":205},[191,1080,1081],{"class":193,"line":251},[191,1082,266],{"emptyLinePlaceholder":43},[191,1084,1085,1087,1089,1091,1093,1095,1097,1100],{"class":193,"line":257},[191,1086,643],{"class":197},[191,1088,646],{"class":604},[191,1090,649],{"class":197},[191,1092,400],{"class":197},[191,1094,1046],{"class":201},[191,1096,278],{"class":205},[191,1098,1099],{"class":224},"\"request timed out\"",[191,1101,411],{"class":205},[191,1103,1104,1106,1108,1111,1113,1115],{"class":193,"line":263},[191,1105,272],{"class":205},[191,1107,275],{"class":201},[191,1109,1110],{"class":205},"(err.name, err ",[191,1112,903],{"class":197},[191,1114,1046],{"class":201},[191,1116,411],{"class":205},[31,1118,1120,1128,1135,1145],{"className":1119},[34],[36,1121,1123,1125,1126],{"className":1122},[39],[41,1124],{"disabled":43,"type":44}," \"TimeoutError\" and ",[22,1127,1019],{},[36,1129,1131,1125,1133],{"className":1130},[39],[41,1132],{"disabled":43,"type":44},[22,1134,696],{},[36,1136,1138,45,1140,1142,1143],{"className":1137},[39],[41,1139],{"disabled":43,"type":44},[22,1141,300],{}," and ",[22,1144,1019],{},[36,1146,1148,1150,1151],{"className":1147},[39],[41,1149],{"disabled":43,"type":44}," \"Error\" and ",[22,1152,1019],{},[100,1154,1155,1157,1164],{},[103,1156,105],{},[107,1158,1159,1161,1162],{},[110,1160,112],{}," D — \"Error\" and ",[22,1163,1019],{},[107,1165,1166,45,1168,1170,1171,1174,1175,1178,1179,1182,1183,1186,1187,1189,1190,1192,1193,1195,1196,1198,1199,1201,1202],{},[110,1167,130],{},[22,1169,987],{},"'s own constructor sets ",[22,1172,1173],{},"this.name"," to ",[22,1176,1177],{},"\"Error\""," by default; simply extending the class does not update ",[22,1180,1181],{},".name"," to match the subclass — you must explicitly set ",[22,1184,1185],{},"this.name = \"TimeoutError\""," (typically right after ",[22,1188,761],{},") for logs and error-reporting tools that read ",[22,1191,1181],{}," to show the right label. Meanwhile ",[22,1194,903],{}," is still ",[22,1197,1019],{}," because it's driven entirely by the prototype chain, a completely independent mechanism from the ",[22,1200,1181],{}," string — which is exactly what trips people up. ",[110,1203,364],{},[14,1205,1206,1210,1286,1332],{"language":174},[17,1207,1209],{"id":1208},"q7-whats-the-problem-with-this-code-and-the-best-fix","Q7. What's the problem with this code, and the best fix?",[180,1211,1212],{"language":174},[183,1213,1215],{"className":185,"code":1214,"language":174,"meta":187,"style":187},"async function saveUser(user) {\n  try {\n    await db.insert(user);\n  } catch (err) {\n    console.error(\"saveUser failed:\", err.message);\n  }\n}\n",[22,1216,1217,1235,1241,1255,1263,1278,1282],{"__ignoreMap":187},[191,1218,1219,1222,1225,1228,1230,1233],{"class":193,"line":194},[191,1220,1221],{"class":197},"async",[191,1223,1224],{"class":197}," function",[191,1226,1227],{"class":201}," saveUser",[191,1229,278],{"class":205},[191,1231,1232],{"class":590},"user",[191,1234,599],{"class":205},[191,1236,1237,1239],{"class":193,"line":209},[191,1238,212],{"class":197},[191,1240,215],{"class":205},[191,1242,1243,1246,1249,1252],{"class":193,"line":218},[191,1244,1245],{"class":197},"    await",[191,1247,1248],{"class":205}," db.",[191,1250,1251],{"class":201},"insert",[191,1253,1254],{"class":205},"(user);\n",[191,1256,1257,1259,1261],{"class":193,"line":231},[191,1258,234],{"class":205},[191,1260,66],{"class":197},[191,1262,892],{"class":205},[191,1264,1265,1267,1270,1272,1275],{"class":193,"line":241},[191,1266,913],{"class":205},[191,1268,1269],{"class":201},"error",[191,1271,278],{"class":205},[191,1273,1274],{"class":224},"\"saveUser failed:\"",[191,1276,1277],{"class":205},", err.message);\n",[191,1279,1280],{"class":193,"line":251},[191,1281,254],{"class":205},[191,1283,1284],{"class":193,"line":257},[191,1285,260],{"class":205},[31,1287,1289,1302,1308,1320],{"className":1288},[34],[36,1290,1292,1294,1295,1297,1298,1301],{"className":1291},[39],[41,1293],{"disabled":43,"type":44}," The ",[22,1296,66],{}," block swallows the error; callers of ",[22,1299,1300],{},"saveUser"," have no way to know it failed unless the error is rethrown after logging",[36,1303,1305,1307],{"className":1304},[39],[41,1306],{"disabled":43,"type":44}," Nothing — logging the error is sufficient error handling",[36,1309,1311,45,1313,1316,1317,1319],{"className":1310},[39],[41,1312],{"disabled":43,"type":44},[22,1314,1315],{},"await"," cannot be used inside a ",[22,1318,51],{}," block",[36,1321,1323,1325,1326,1328,1329],{"className":1322},[39],[41,1324],{"disabled":43,"type":44}," The error should be logged with ",[22,1327,471],{}," instead of ",[22,1330,1331],{},"console.error",[100,1333,1334,1336,1345],{},[103,1335,105],{},[107,1337,1338,1340,1341,1297,1343,1301],{},[110,1339,112],{}," A — The ",[22,1342,66],{},[22,1344,1300],{},[107,1346,1347,1349,1350,1352,1353,1356,1357,1360,1361],{},[110,1348,130],{}," Logging without rethrowing lets ",[22,1351,1300],{},"'s returned promise resolve successfully even though the insert failed — any caller doing ",[22,1354,1355],{},"await saveUser(user)"," has no way to detect the failure and proceeds as if it succeeded. The log-and-rethrow pattern (log for diagnostics, then ",[22,1358,1359],{},"throw err"," or a wrapped error) keeps both observability and correct control flow intact. ",[110,1362,1363],{},"Idiom",[14,1365,1366,1370,1498,1558],{"language":174},[17,1367,1369],{"id":1368},"q8-compare-the-two-functions-below-which-statement-is-correct","Q8. Compare the two functions below. Which statement is correct?",[180,1371,1372],{"language":174},[183,1373,1375],{"className":185,"code":1374,"language":174,"meta":187,"style":187},"function readFile(path) {\n  try {\n    return fs.readFileSync(path);\n  } catch (err) {\n    throw err;\n  }\n}\n\nfunction readFileWrapped(path) {\n  try {\n    return fs.readFileSync(path);\n  } catch (err) {\n    throw new Error(\"read failed\");\n  }\n}\n",[22,1376,1377,1391,1397,1410,1418,1425,1429,1433,1437,1450,1456,1466,1474,1489,1493],{"__ignoreMap":187},[191,1378,1379,1381,1384,1386,1389],{"class":193,"line":194},[191,1380,198],{"class":197},[191,1382,1383],{"class":201}," readFile",[191,1385,278],{"class":205},[191,1387,1388],{"class":590},"path",[191,1390,599],{"class":205},[191,1392,1393,1395],{"class":193,"line":209},[191,1394,212],{"class":197},[191,1396,215],{"class":205},[191,1398,1399,1401,1404,1407],{"class":193,"line":218},[191,1400,221],{"class":197},[191,1402,1403],{"class":205}," fs.",[191,1405,1406],{"class":201},"readFileSync",[191,1408,1409],{"class":205},"(path);\n",[191,1411,1412,1414,1416],{"class":193,"line":231},[191,1413,234],{"class":205},[191,1415,66],{"class":197},[191,1417,892],{"class":205},[191,1419,1420,1422],{"class":193,"line":241},[191,1421,397],{"class":197},[191,1423,1424],{"class":205}," err;\n",[191,1426,1427],{"class":193,"line":251},[191,1428,254],{"class":205},[191,1430,1431],{"class":193,"line":257},[191,1432,260],{"class":205},[191,1434,1435],{"class":193,"line":263},[191,1436,266],{"emptyLinePlaceholder":43},[191,1438,1439,1441,1444,1446,1448],{"class":193,"line":269},[191,1440,198],{"class":197},[191,1442,1443],{"class":201}," readFileWrapped",[191,1445,278],{"class":205},[191,1447,1388],{"class":590},[191,1449,599],{"class":205},[191,1451,1452,1454],{"class":193,"line":884},[191,1453,212],{"class":197},[191,1455,215],{"class":205},[191,1457,1458,1460,1462,1464],{"class":193,"line":895},[191,1459,221],{"class":197},[191,1461,1403],{"class":205},[191,1463,1406],{"class":201},[191,1465,1409],{"class":205},[191,1467,1468,1470,1472],{"class":193,"line":910},[191,1469,234],{"class":205},[191,1471,66],{"class":197},[191,1473,892],{"class":205},[191,1475,1476,1478,1480,1482,1484,1487],{"class":193,"line":932},[191,1477,397],{"class":197},[191,1479,400],{"class":197},[191,1481,403],{"class":201},[191,1483,278],{"class":205},[191,1485,1486],{"class":224},"\"read failed\"",[191,1488,411],{"class":205},[191,1490,1491],{"class":193,"line":937},[191,1492,254],{"class":205},[191,1494,1496],{"class":193,"line":1495},15,[191,1497,260],{"class":205},[31,1499,1501,1515,1521,1547],{"className":1500},[34],[36,1502,1504,1506,1507,1510,1511,1514],{"className":1503},[39],[41,1505],{"disabled":43,"type":44}," Both functions produce an error whose ",[22,1508,1509],{},".stack"," points to the original ",[22,1512,1513],{},"fs.readFileSync"," failure",[36,1516,1518,1520],{"className":1517},[39],[41,1519],{"disabled":43,"type":44}," Neither function preserves any stack information once the error is caught",[36,1522,1524,45,1526,1529,1530,1532,1533,1536,1537,1539,1540,1543,1544],{"className":1523},[39],[41,1525],{"disabled":43,"type":44},[22,1527,1528],{},"readFile","'s rethrown error keeps its original ",[22,1531,1509],{}," (captured when it was first constructed), but ",[22,1534,1535],{},"readFileWrapped"," creates a brand-new error whose ",[22,1538,1509],{}," starts at the ",[22,1541,1542],{},"new Error(\"read failed\")"," line, losing the original failure site unless passed via ",[22,1545,1546],{},"cause",[36,1548,1550,45,1552,1554,1555,1557],{"className":1549},[39],[41,1551],{"disabled":43,"type":44},[22,1553,1535],{}," automatically appends the original error's stack to the new error's ",[22,1556,1509],{}," property",[100,1559,1560,1562,1577],{},[103,1561,105],{},[107,1563,1564,1566,1567,1529,1569,1571,1572,1574,1575],{},[110,1565,112],{}," C — ",[22,1568,1528],{},[22,1570,1509],{},", but ",[22,1573,1535],{}," loses it unless passed via ",[22,1576,1546],{},[107,1578,1579,1581,1582,358,1584,1586,1587,496,1589,1591,1592,1594,1595,1597,1598,1600,1601,1603,1604,1606,1607,1609,1610,546,1613],{},[110,1580,130],{}," An ",[22,1583,987],{},[22,1585,1509],{}," is captured once, at construction time — not at throw time. ",[22,1588,1359],{},[22,1590,1528],{}," rethrows the exact same object, so ",[22,1593,1509],{}," still shows where ",[22,1596,1513],{}," originally failed. ",[22,1599,1535],{}," constructs a brand-new ",[22,1602,987],{},", so its ",[22,1605,1509],{}," starts fresh at the ",[22,1608,1542],{}," line; the original failure location is lost unless explicitly preserved, e.g. ",[22,1611,1612],{},"new Error(\"read failed\", { cause: err })",[110,1614,364],{},[14,1616,1617,1621,1716,1763],{"language":174},[17,1618,1620],{"id":1619},"q9-what-does-this-log","Q9. What does this log?",[180,1622,1623],{"language":174},[183,1624,1626],{"className":185,"code":1625,"language":174,"meta":187,"style":187},"function checkAge(age) {\n  if (age \u003C 0) throw \"invalid age\";\n}\n\ntry {\n  checkAge(-5);\n} catch (err) {\n  console.log(err.message, err.stack);\n}\n",[22,1627,1628,1642,1665,1669,1673,1679,1694,1702,1712],{"__ignoreMap":187},[191,1629,1630,1632,1635,1637,1640],{"class":193,"line":194},[191,1631,198],{"class":197},[191,1633,1634],{"class":201}," checkAge",[191,1636,278],{"class":205},[191,1638,1639],{"class":590},"age",[191,1641,599],{"class":205},[191,1643,1644,1646,1649,1652,1655,1658,1660,1663],{"class":193,"line":209},[191,1645,833],{"class":197},[191,1647,1648],{"class":205}," (age ",[191,1650,1651],{"class":197},"\u003C",[191,1653,1654],{"class":604}," 0",[191,1656,1657],{"class":205},") ",[191,1659,144],{"class":197},[191,1661,1662],{"class":224}," \"invalid age\"",[191,1664,228],{"class":205},[191,1666,1667],{"class":193,"line":218},[191,1668,260],{"class":205},[191,1670,1671],{"class":193,"line":231},[191,1672,266],{"emptyLinePlaceholder":43},[191,1674,1675,1677],{"class":193,"line":241},[191,1676,51],{"class":197},[191,1678,215],{"class":205},[191,1680,1681,1684,1686,1689,1692],{"class":193,"line":251},[191,1682,1683],{"class":201},"  checkAge",[191,1685,278],{"class":205},[191,1687,1688],{"class":197},"-",[191,1690,1691],{"class":604},"5",[191,1693,411],{"class":205},[191,1695,1696,1698,1700],{"class":193,"line":257},[191,1697,887],{"class":205},[191,1699,66],{"class":197},[191,1701,892],{"class":205},[191,1703,1704,1707,1709],{"class":193,"line":263},[191,1705,1706],{"class":205},"  console.",[191,1708,275],{"class":201},[191,1710,1711],{"class":205},"(err.message, err.stack);\n",[191,1713,1714],{"class":193,"line":269},[191,1715,260],{"class":205},[31,1717,1719,1725,1739,1750],{"className":1718},[34],[36,1720,1722,1724],{"className":1721},[39],[41,1723],{"disabled":43,"type":44}," \"invalid age\" and a full stack trace are logged",[36,1726,1728,45,1730,1733,1734,70,1737,1557],{"className":1727},[39],[41,1729],{"disabled":43,"type":44},[22,1731,1732],{},"undefined undefined"," is logged, because a thrown string has no ",[22,1735,1736],{},".message",[22,1738,1509],{},[36,1740,1742,306,1744,1746,1747,1749],{"className":1741},[39],[41,1743],{"disabled":43,"type":44},[22,1745,486],{}," is thrown because only ",[22,1748,987],{}," instances can be thrown",[36,1751,1753,45,1755,1757,1758,1760,1761],{"className":1752},[39],[41,1754],{"disabled":43,"type":44},[22,1756,676],{}," is automatically wrapped into an ",[22,1759,987],{}," object by the JS engine before reaching ",[22,1762,66],{},[100,1764,1765,1767,1777],{},[103,1766,105],{},[107,1768,1769,113,1771,1733,1773,70,1775,1557],{},[110,1770,112],{},[22,1772,1732],{},[22,1774,1736],{},[22,1776,1509],{},[107,1778,1779,1781,1782,1784,1785,1787,1788,1791,1792,334,1794,1796,1797,1800,1801,70,1803,1805,1806,1808,1809,1812,1813,63,1815,63,1817,1819,1820],{},[110,1780,130],{}," JavaScript allows ",[22,1783,144],{}," on any value — strings, numbers, plain objects — not only ",[22,1786,987],{}," instances. ",[22,1789,1790],{},"throw \"invalid age\""," means ",[22,1793,676],{},[22,1795,66],{}," is literally the string ",[22,1798,1799],{},"\"invalid age\"",", which has no ",[22,1802,1736],{},[22,1804,1509],{},", so both log as ",[22,1807,300],{},". This is a real anti-pattern: always ",[22,1810,1811],{},"throw new Error(...)"," (or a subclass) so consuming code and tooling — debuggers, error trackers, logging libraries — can rely on ",[22,1814,1736],{},[22,1816,1509],{},[22,1818,1181],{}," existing. ",[110,1821,552],{},[14,1823,1824,1832,1982,2017],{"language":174},[17,1825,1827,1828,1831],{"id":1826},"q10-what-happens-when-handlerequest-runs","Q10. What happens when ",[22,1829,1830],{},"handleRequest"," runs?",[180,1833,1834],{"language":174},[183,1835,1837],{"className":185,"code":1836,"language":174,"meta":187,"style":187},"async function processOrder(order) {\n  if (!order.items.length) throw new Error(\"empty order\");\n  return \"processed\";\n}\n\nfunction handleRequest(order) {\n  try {\n    processOrder(order);\n    console.log(\"request accepted\");\n  } catch (err) {\n    console.log(\"caught:\", err.message);\n  }\n}\n\nhandleRequest({ items: [] });\n",[22,1838,1839,1855,1884,1894,1898,1902,1915,1921,1929,1942,1950,1963,1967,1971,1975],{"__ignoreMap":187},[191,1840,1841,1843,1845,1848,1850,1853],{"class":193,"line":194},[191,1842,1221],{"class":197},[191,1844,1224],{"class":197},[191,1846,1847],{"class":201}," processOrder",[191,1849,278],{"class":205},[191,1851,1852],{"class":590},"order",[191,1854,599],{"class":205},[191,1856,1857,1859,1861,1863,1866,1869,1871,1873,1875,1877,1879,1882],{"class":193,"line":209},[191,1858,833],{"class":197},[191,1860,836],{"class":205},[191,1862,839],{"class":197},[191,1864,1865],{"class":205},"order.items.",[191,1867,1868],{"class":604},"length",[191,1870,1657],{"class":205},[191,1872,144],{"class":197},[191,1874,400],{"class":197},[191,1876,403],{"class":201},[191,1878,278],{"class":205},[191,1880,1881],{"class":224},"\"empty order\"",[191,1883,411],{"class":205},[191,1885,1886,1889,1892],{"class":193,"line":218},[191,1887,1888],{"class":197},"  return",[191,1890,1891],{"class":224}," \"processed\"",[191,1893,228],{"class":205},[191,1895,1896],{"class":193,"line":231},[191,1897,260],{"class":205},[191,1899,1900],{"class":193,"line":241},[191,1901,266],{"emptyLinePlaceholder":43},[191,1903,1904,1906,1909,1911,1913],{"class":193,"line":251},[191,1905,198],{"class":197},[191,1907,1908],{"class":201}," handleRequest",[191,1910,278],{"class":205},[191,1912,1852],{"class":590},[191,1914,599],{"class":205},[191,1916,1917,1919],{"class":193,"line":257},[191,1918,212],{"class":197},[191,1920,215],{"class":205},[191,1922,1923,1926],{"class":193,"line":263},[191,1924,1925],{"class":201},"    processOrder",[191,1927,1928],{"class":205},"(order);\n",[191,1930,1931,1933,1935,1937,1940],{"class":193,"line":269},[191,1932,913],{"class":205},[191,1934,275],{"class":201},[191,1936,278],{"class":205},[191,1938,1939],{"class":224},"\"request accepted\"",[191,1941,411],{"class":205},[191,1943,1944,1946,1948],{"class":193,"line":884},[191,1945,234],{"class":205},[191,1947,66],{"class":197},[191,1949,892],{"class":205},[191,1951,1952,1954,1956,1958,1961],{"class":193,"line":895},[191,1953,913],{"class":205},[191,1955,275],{"class":201},[191,1957,278],{"class":205},[191,1959,1960],{"class":224},"\"caught:\"",[191,1962,1277],{"class":205},[191,1964,1965],{"class":193,"line":910},[191,1966,254],{"class":205},[191,1968,1969],{"class":193,"line":932},[191,1970,260],{"class":205},[191,1972,1973],{"class":193,"line":937},[191,1974,266],{"emptyLinePlaceholder":43},[191,1976,1977,1979],{"class":193,"line":1495},[191,1978,1830],{"class":201},[191,1980,1981],{"class":205},"({ items: [] });\n",[31,1983,1985,1991,1999,2007],{"className":1984},[34],[36,1986,1988,1990],{"className":1987},[39],[41,1989],{"disabled":43,"type":44}," \"caught: empty order\" is logged",[36,1992,1994,948,1996,1998],{"className":1993},[39],[41,1995],{"disabled":43,"type":44},[22,1997,1830],{}," throws synchronously",[36,2000,2002,1294,2004,2006],{"className":2001},[39],[41,2003],{"disabled":43,"type":44},[22,2005,66],{}," block runs before \"request accepted\" is logged",[36,2008,2010,2012,2013,2016],{"className":2009},[39],[41,2011],{"disabled":43,"type":44}," \"request accepted\" is logged, and the rejection from ",[22,2014,2015],{},"processOrder"," becomes an unhandled promise rejection instead of being caught",[100,2018,2019,2021,2028],{},[103,2020,105],{},[107,2022,2023,2025,2026,2016],{},[110,2024,112],{}," D — \"request accepted\" is logged, and the rejection from ",[22,2027,2015],{},[107,2029,2030,45,2032,693,2034,2036,2037,2039,2040,2042,2043,2046,2047,2049,2050,2052,2053,2056,2057,2060,2061,2063,2064,546,2067],{},[110,2031,130],{},[22,2033,2015],{},[22,2035,1221],{},", so calling it without ",[22,2038,1315],{}," immediately returns a pending promise — the ",[22,2041,144],{}," inside it rejects that promise rather than throwing synchronously. The surrounding ",[22,2044,2045],{},"try\u002Fcatch"," only catches synchronous throws (or ",[22,2048,1315],{},"ed rejections), so it never sees this one. ",[22,2051,1939],{}," logs right away, and the rejection later surfaces as an ",[22,2054,2055],{},"unhandledrejection"," event. The fix is to ",[22,2058,2059],{},"await processOrder(order)"," inside the ",[22,2062,51],{},", or chain an explicit ",[22,2065,2066],{},".catch()",[110,2068,364],{},[14,2070,2071,2079,2196,2247],{"language":174},[17,2072,2074,2075,2078],{"id":2073},"q11-what-happens-if-the-request-inside-fetchprofile-fails","Q11. What happens if the request inside ",[22,2076,2077],{},"fetchProfile"," fails?",[180,2080,2081],{"language":174},[183,2082,2084],{"className":185,"code":2083,"language":174,"meta":187,"style":187},"function fetchProfile(id) {\n  return api.get(`\u002Fusers\u002F${id}`)\n    .catch(err => console.error(\"fetch failed:\", err));\n}\n\nfetchProfile(42).then(profile => {\n  console.log(profile.name);\n});\n",[22,2085,2086,2100,2123,2150,2154,2158,2182,2191],{"__ignoreMap":187},[191,2087,2088,2090,2093,2095,2098],{"class":193,"line":194},[191,2089,198],{"class":197},[191,2091,2092],{"class":201}," fetchProfile",[191,2094,278],{"class":205},[191,2096,2097],{"class":590},"id",[191,2099,599],{"class":205},[191,2101,2102,2104,2107,2110,2112,2115,2117,2120],{"class":193,"line":209},[191,2103,1888],{"class":197},[191,2105,2106],{"class":205}," api.",[191,2108,2109],{"class":201},"get",[191,2111,278],{"class":205},[191,2113,2114],{"class":224},"`\u002Fusers\u002F${",[191,2116,2097],{"class":205},[191,2118,2119],{"class":224},"}`",[191,2121,2122],{"class":205},")\n",[191,2124,2125,2128,2130,2132,2134,2137,2140,2142,2144,2147],{"class":193,"line":218},[191,2126,2127],{"class":205},"    .",[191,2129,66],{"class":201},[191,2131,278],{"class":205},[191,2133,676],{"class":590},[191,2135,2136],{"class":197}," =>",[191,2138,2139],{"class":205}," console.",[191,2141,1269],{"class":201},[191,2143,278],{"class":205},[191,2145,2146],{"class":224},"\"fetch failed:\"",[191,2148,2149],{"class":205},", err));\n",[191,2151,2152],{"class":193,"line":231},[191,2153,260],{"class":205},[191,2155,2156],{"class":193,"line":241},[191,2157,266],{"emptyLinePlaceholder":43},[191,2159,2160,2162,2164,2167,2170,2173,2175,2178,2180],{"class":193,"line":251},[191,2161,2077],{"class":201},[191,2163,278],{"class":205},[191,2165,2166],{"class":604},"42",[191,2168,2169],{"class":205},").",[191,2171,2172],{"class":201},"then",[191,2174,278],{"class":205},[191,2176,2177],{"class":590},"profile",[191,2179,2136],{"class":197},[191,2181,215],{"class":205},[191,2183,2184,2186,2188],{"class":193,"line":257},[191,2185,1706],{"class":205},[191,2187,275],{"class":201},[191,2189,2190],{"class":205},"(profile.name);\n",[191,2192,2193],{"class":193,"line":263},[191,2194,2195],{"class":205},"});\n",[31,2197,2199,2218,2227,2239],{"className":2198},[34],[36,2200,2202,45,2204,693,2206,334,2208,2211,2212,2214,2215],{"className":2201},[39],[41,2203],{"disabled":43,"type":44},[22,2205,2177],{},[22,2207,300],{},[22,2209,2210],{},".then",", causing a ",[22,2213,486],{}," when accessing ",[22,2216,2217],{},"profile.name",[36,2219,2221,2223,2224,2226],{"className":2220},[39],[41,2222],{"disabled":43,"type":44}," If the request fails, ",[22,2225,2210],{}," never runs",[36,2228,2230,1294,2232,2235,2236,2238],{"className":2229},[39],[41,2231],{"disabled":43,"type":44},[22,2233,2234],{},".catch"," rethrows automatically, so ",[22,2237,2210],{}," is skipped on failure",[36,2240,2242,45,2244,2246],{"className":2241},[39],[41,2243],{"disabled":43,"type":44},[22,2245,2077],{}," returns a rejected promise on failure, which propagates correctly to the caller",[100,2248,2249,2251,2266],{},[103,2250,105],{},[107,2252,2253,2255,2256,693,2258,334,2260,2211,2262,2214,2264],{},[110,2254,112],{}," A — ",[22,2257,2177],{},[22,2259,300],{},[22,2261,2210],{},[22,2263,486],{},[22,2265,2217],{},[107,2267,2268,306,2270,2272,2273,2275,2276,2278,2279,2282,2283,693,2285,2287,2288,2290,2291,2293,2294,2296,2297],{},[110,2269,130],{},[22,2271,2066],{}," handler that only logs (and returns nothing) recovers the promise chain — its return value, ",[22,2274,300],{},", becomes the resolved value of the promise ",[22,2277,2077],{}," returns. So on failure, ",[22,2280,2281],{},".then(profile => ...)"," still runs, but ",[22,2284,2177],{},[22,2286,300],{},", and ",[22,2289,2217],{}," throws a fresh ",[22,2292,486],{}," far from the real cause. To propagate the failure instead of masking it, the ",[22,2295,66],{}," handler must rethrow (or the caller shouldn't swallow it there at all). ",[110,2298,1363],{},[14,2300,2301,2305,2435,2475],{"language":174},[17,2302,2304],{"id":2303},"q12-what-does-this-log","Q12. What does this log?",[180,2306,2307],{"language":174},[183,2308,2310],{"className":185,"code":2309,"language":174,"meta":187,"style":187},"async function loadUser(id) {\n  try {\n    return await db.query(id);\n  } catch (err) {\n    throw new Error(\"failed to load user\", { cause: err });\n  }\n}\n\ntry {\n  await loadUser(1);\n} catch (e) {\n  console.log(e.message);\n  console.log(e.cause.message);\n}\n",[22,2311,2312,2327,2333,2348,2356,2372,2376,2380,2384,2390,2404,2413,2422,2431],{"__ignoreMap":187},[191,2313,2314,2316,2318,2321,2323,2325],{"class":193,"line":194},[191,2315,1221],{"class":197},[191,2317,1224],{"class":197},[191,2319,2320],{"class":201}," loadUser",[191,2322,278],{"class":205},[191,2324,2097],{"class":590},[191,2326,599],{"class":205},[191,2328,2329,2331],{"class":193,"line":209},[191,2330,212],{"class":197},[191,2332,215],{"class":205},[191,2334,2335,2337,2340,2342,2345],{"class":193,"line":218},[191,2336,221],{"class":197},[191,2338,2339],{"class":197}," await",[191,2341,1248],{"class":205},[191,2343,2344],{"class":201},"query",[191,2346,2347],{"class":205},"(id);\n",[191,2349,2350,2352,2354],{"class":193,"line":231},[191,2351,234],{"class":205},[191,2353,66],{"class":197},[191,2355,892],{"class":205},[191,2357,2358,2360,2362,2364,2366,2369],{"class":193,"line":241},[191,2359,397],{"class":197},[191,2361,400],{"class":197},[191,2363,403],{"class":201},[191,2365,278],{"class":205},[191,2367,2368],{"class":224},"\"failed to load user\"",[191,2370,2371],{"class":205},", { cause: err });\n",[191,2373,2374],{"class":193,"line":251},[191,2375,254],{"class":205},[191,2377,2378],{"class":193,"line":257},[191,2379,260],{"class":205},[191,2381,2382],{"class":193,"line":263},[191,2383,266],{"emptyLinePlaceholder":43},[191,2385,2386,2388],{"class":193,"line":269},[191,2387,51],{"class":197},[191,2389,215],{"class":205},[191,2391,2392,2395,2397,2399,2402],{"class":193,"line":884},[191,2393,2394],{"class":197},"  await",[191,2396,2320],{"class":201},[191,2398,278],{"class":205},[191,2400,2401],{"class":604},"1",[191,2403,411],{"class":205},[191,2405,2406,2408,2410],{"class":193,"line":895},[191,2407,887],{"class":205},[191,2409,66],{"class":197},[191,2411,2412],{"class":205}," (e) {\n",[191,2414,2415,2417,2419],{"class":193,"line":910},[191,2416,1706],{"class":205},[191,2418,275],{"class":201},[191,2420,2421],{"class":205},"(e.message);\n",[191,2423,2424,2426,2428],{"class":193,"line":932},[191,2425,1706],{"class":205},[191,2427,275],{"class":201},[191,2429,2430],{"class":205},"(e.cause.message);\n",[191,2432,2433],{"class":193,"line":937},[191,2434,260],{"class":205},[31,2436,2438,2444,2458,2464],{"className":2437},[34],[36,2439,2441,2443],{"className":2440},[39],[41,2442],{"disabled":43,"type":44}," Only the original database error's message is logged",[36,2445,2447,2449,2450,2452,2453,2455,2456,1557],{"className":2446},[39],[41,2448],{"disabled":43,"type":44}," \"failed to load user\" then ",[22,2451,300],{},", because ",[22,2454,1546],{}," is not a real ",[22,2457,987],{},[36,2459,2461,2463],{"className":2460},[39],[41,2462],{"disabled":43,"type":44}," \"failed to load user\" then the original database error's message",[36,2465,2467,306,2469,2471,2472,2474],{"className":2466},[39],[41,2468],{"disabled":43,"type":44},[22,2470,309],{}," because ",[22,2473,987],{}," does not accept a second argument",[100,2476,2477,2479,2484],{},[103,2478,105],{},[107,2480,2481,2483],{},[110,2482,112],{}," C — \"failed to load user\" then the original database error's message",[107,2485,2486,2488,2489,45,2491,2493,2494,2497,2498,2500,2501,2503,2504],{},[110,2487,130],{}," The ES2022 ",[22,2490,987],{},[22,2492,1546],{}," option lets you construct a new, higher-level error while preserving the original one on ",[22,2495,2496],{},"e.cause",", so downstream code (or a debugger) can inspect both the friendly outer message and the root technical cause without losing information the way plain re-wrapping does. B is wrong because ",[22,2499,1546],{}," has been a standard, widely-supported ",[22,2502,987],{}," constructor option since ES2022. ",[110,2505,1363],{},[14,2507,2508,2512,2627,2684],{"language":174},[17,2509,2511],{"id":2510},"q13-is-this-valid-javascript-and-what-does-it-demonstrate","Q13. Is this valid JavaScript, and what does it demonstrate?",[180,2513,2514],{"language":174},[183,2515,2517],{"className":185,"code":2516,"language":174,"meta":187,"style":187},"try {\n  JSON.parse(rawInput);\n} catch (err) {\n  if (err instanceof SyntaxError) {\n    console.log(\"bad JSON\");\n  } else if (err instanceof TypeError) {\n    console.log(\"bad input type\");\n  } else {\n    throw err;\n  }\n}\n",[22,2518,2519,2525,2539,2547,2560,2573,2592,2605,2613,2619,2623],{"__ignoreMap":187},[191,2520,2521,2523],{"class":193,"line":194},[191,2522,51],{"class":197},[191,2524,215],{"class":205},[191,2526,2527,2530,2533,2536],{"class":193,"line":209},[191,2528,2529],{"class":604},"  JSON",[191,2531,2532],{"class":205},".",[191,2534,2535],{"class":201},"parse",[191,2537,2538],{"class":205},"(rawInput);\n",[191,2540,2541,2543,2545],{"class":193,"line":218},[191,2542,887],{"class":205},[191,2544,66],{"class":197},[191,2546,892],{"class":205},[191,2548,2549,2551,2553,2555,2558],{"class":193,"line":231},[191,2550,833],{"class":197},[191,2552,900],{"class":205},[191,2554,903],{"class":197},[191,2556,2557],{"class":201}," SyntaxError",[191,2559,599],{"class":205},[191,2561,2562,2564,2566,2568,2571],{"class":193,"line":241},[191,2563,913],{"class":205},[191,2565,275],{"class":201},[191,2567,278],{"class":205},[191,2569,2570],{"class":224},"\"bad JSON\"",[191,2572,411],{"class":205},[191,2574,2575,2577,2580,2583,2585,2587,2590],{"class":193,"line":251},[191,2576,234],{"class":205},[191,2578,2579],{"class":197},"else",[191,2581,2582],{"class":197}," if",[191,2584,900],{"class":205},[191,2586,903],{"class":197},[191,2588,2589],{"class":201}," TypeError",[191,2591,599],{"class":205},[191,2593,2594,2596,2598,2600,2603],{"class":193,"line":257},[191,2595,913],{"class":205},[191,2597,275],{"class":201},[191,2599,278],{"class":205},[191,2601,2602],{"class":224},"\"bad input type\"",[191,2604,411],{"class":205},[191,2606,2607,2609,2611],{"class":193,"line":263},[191,2608,234],{"class":205},[191,2610,2579],{"class":197},[191,2612,215],{"class":205},[191,2614,2615,2617],{"class":193,"line":269},[191,2616,397],{"class":197},[191,2618,1424],{"class":205},[191,2620,2621],{"class":193,"line":884},[191,2622,254],{"class":205},[191,2624,2625],{"class":193,"line":895},[191,2626,260],{"class":205},[31,2628,2630,2642,2657,2674],{"className":2629},[34],[36,2631,2633,2635,2636,2638,2639],{"className":2632},[39],[41,2634],{"disabled":43,"type":44}," This code is invalid — JavaScript requires a separate ",[22,2637,66],{}," clause per error type, like ",[22,2640,2641],{},"catch (SyntaxError e)",[36,2643,2645,2647,2648,2650,2651,2653,2654,2656],{"className":2644},[39],[41,2646],{"disabled":43,"type":44}," JavaScript has only one ",[22,2649,66],{}," clause per ",[22,2652,51],{},"; differentiating error types is done manually with ",[22,2655,903],{}," checks inside it, as shown here",[36,2658,2660,45,2662,2665,2666,2471,2668,2671,2672],{"className":2659},[39],[41,2661],{"disabled":43,"type":44},[22,2663,2664],{},"instanceof SyntaxError"," will never be ",[22,2667,1019],{},[22,2669,2670],{},"JSON.parse"," throws a plain ",[22,2673,987],{},[36,2675,2677,1294,2679,2681,2682],{"className":2676},[39],[41,2678],{"disabled":43,"type":44},[22,2680,2579],{}," branch causes an infinite loop by re-throwing inside a ",[22,2683,66],{},[100,2685,2686,2688,2699],{},[103,2687,105],{},[107,2689,2690,2692,2693,2650,2695,2653,2697,2656],{},[110,2691,112],{}," B — JavaScript has only one ",[22,2694,66],{},[22,2696,51],{},[22,2698,903],{},[107,2700,2701,2703,2704,2706,2707,2709,2710,2712,2713,2715,2716,2718,2719,2721],{},[110,2702,130],{}," Unlike languages such as Java or Python that support multiple typed ",[22,2705,66],{}," clauses, JavaScript's ",[22,2708,51],{}," statement allows exactly one ",[22,2711,66],{}," block. The idiomatic way to branch on error type is ",[22,2714,903],{}," checks inside that single block, rethrowing (or handling generically) anything unrecognized. ",[22,2717,2670],{}," genuinely throws a ",[22,2720,309],{}," on malformed JSON, so C is false, and A describes syntax that doesn't exist in JS.",[14,2723,2724,2728,2804,2845],{"language":174},[17,2725,2727],{"id":2726},"q14-what-is-this-syntax-and-when-is-it-appropriate","Q14. What is this syntax, and when is it appropriate?",[180,2729,2730],{"language":174},[183,2731,2733],{"className":185,"code":2732,"language":174,"meta":187,"style":187},"async function isPortAvailable(port) {\n  try {\n    await net.connect(port);\n    return false;\n  } catch {\n    return true;\n  }\n}\n",[22,2734,2735,2751,2757,2770,2779,2787,2796,2800],{"__ignoreMap":187},[191,2736,2737,2739,2741,2744,2746,2749],{"class":193,"line":194},[191,2738,1221],{"class":197},[191,2740,1224],{"class":197},[191,2742,2743],{"class":201}," isPortAvailable",[191,2745,278],{"class":205},[191,2747,2748],{"class":590},"port",[191,2750,599],{"class":205},[191,2752,2753,2755],{"class":193,"line":209},[191,2754,212],{"class":197},[191,2756,215],{"class":205},[191,2758,2759,2761,2764,2767],{"class":193,"line":218},[191,2760,1245],{"class":197},[191,2762,2763],{"class":205}," net.",[191,2765,2766],{"class":201},"connect",[191,2768,2769],{"class":205},"(port);\n",[191,2771,2772,2774,2777],{"class":193,"line":231},[191,2773,221],{"class":197},[191,2775,2776],{"class":604}," false",[191,2778,228],{"class":205},[191,2780,2781,2783,2785],{"class":193,"line":241},[191,2782,234],{"class":205},[191,2784,66],{"class":197},[191,2786,215],{"class":205},[191,2788,2789,2791,2794],{"class":193,"line":251},[191,2790,221],{"class":197},[191,2792,2793],{"class":604}," true",[191,2795,228],{"class":205},[191,2797,2798],{"class":193,"line":257},[191,2799,254],{"class":205},[191,2801,2802],{"class":193,"line":263},[191,2803,260],{"class":205},[31,2805,2807,2819,2830,2839],{"className":2806},[34],[36,2808,2810,2812,2813,2815,2816],{"className":2809},[39],[41,2811],{"disabled":43,"type":44}," This is a syntax error — ",[22,2814,66],{}," always requires a parenthesized parameter like ",[22,2817,2818],{},"catch (err)",[36,2820,2822,45,2824,2826,2827,2829],{"className":2821},[39],[41,2823],{"disabled":43,"type":44},[22,2825,66],{}," without a parameter silently ignores only ",[22,2828,486],{},"s and lets everything else propagate",[36,2831,2833,2835,2836,2838],{"className":2832},[39],[41,2834],{"disabled":43,"type":44}," This works, but ",[22,2837,676],{}," is still implicitly available as a global variable inside the block",[36,2840,2842,2844],{"className":2841},[39],[41,2843],{"disabled":43,"type":44}," This is valid ES2019+ syntax called optional catch binding, used when the caught error's details aren't needed",[100,2846,2847,2849,2854],{},[103,2848,105],{},[107,2850,2851,2853],{},[110,2852,112],{}," D — This is valid ES2019+ syntax called optional catch binding, used when the caught error's details aren't needed",[107,2855,2856,2858,2859,2862,2863,2866,2867,2870,2871,2874,2875],{},[110,2857,130],{}," Optional catch binding (",[22,2860,2861],{},"catch { ... }"," with no ",[22,2864,2865],{},"(err)",") has been valid syntax since ES2019 for exactly this situation — reacting to the fact that something failed without needing the error object itself. It's cleaner than ",[22,2868,2869],{},"catch (_)"," or an unused ",[22,2872,2873],{},"catch (err) { ... }"," parameter and avoids unused-variable lint warnings. ",[110,2876,1363],{},[14,2878,2879,2893,2923],{},[17,2880,2882,2883,2886,2887,2889,2890,2892],{"id":2881},"q15-why-are-windowonerror-and-the-unhandledrejection-event-described-as-last-resort-global-error-handlers-rather-than-a-replacement-for-local-trycatch","Q15. Why are ",[22,2884,2885],{},"window.onerror"," and the ",[22,2888,2055],{}," event described as \"last resort\" global error handlers rather than a replacement for local ",[22,2891,2045],{},"?",[31,2894,2896,2902,2908,2914],{"className":2895},[34],[36,2897,2899,2901],{"className":2898},[39],[41,2900],{"disabled":43,"type":44}," By the time they fire, the error has already escaped its original context — you've lost the chance to retry, show inline UI feedback, or recover gracefully; they're best used for logging\u002Freporting errors that were missed locally",[36,2903,2905,2907],{"className":2904},[39],[41,2906],{"disabled":43,"type":44}," They only fire in browsers, not in Node.js, so relying on them breaks server-side code",[36,2909,2911,2913],{"className":2910},[39],[41,2912],{"disabled":43,"type":44}," They automatically retry the failed operation, which is usually undesirable",[36,2915,2917,2919,2920,2922],{"className":2916},[39],[41,2918],{"disabled":43,"type":44}," They can only catch errors thrown inside ",[22,2921,51],{}," blocks, not truly uncaught ones",[100,2924,2925,2927,2932],{},[103,2926,105],{},[107,2928,2929,2931],{},[110,2930,112],{}," A — By the time they fire, the error has already escaped its original context — you've lost the chance to retry, show inline UI feedback, or recover gracefully; they're best used for logging\u002Freporting errors that were missed locally",[107,2933,2934,2936,2937,63,2940,2943],{},[110,2935,130],{}," Global handlers are a safety net for observability, e.g. shipping errors to a monitoring service, but they run after the stack has already unwound, so there's no way to resume the original operation, show contextual UI, or apply targeted recovery logic. Meaningful recovery requires catching close to the failure. B is false (Node has its analogous ",[22,2938,2939],{},"process.on('uncaughtException')",[22,2941,2942],{},"process.on('unhandledRejection')","); D is false — they exist specifically to catch what wasn't caught locally.",[14,2945,2946,2953,3053,3097],{"language":174},[17,2947,2949,2950,1831],{"id":2948},"q16-what-happens-when-schedulework-runs","Q16. What happens when ",[22,2951,2952],{},"scheduleWork",[180,2954,2955],{"language":174},[183,2956,2958],{"className":185,"code":2957,"language":174,"meta":187,"style":187},"function scheduleWork() {\n  try {\n    setTimeout(() => {\n      throw new Error(\"boom\");\n    }, 100);\n  } catch (err) {\n    console.log(\"caught:\", err.message);\n  }\n}\n\nscheduleWork();\n",[22,2959,2960,2969,2975,2988,3004,3014,3022,3034,3038,3042,3046],{"__ignoreMap":187},[191,2961,2962,2964,2967],{"class":193,"line":194},[191,2963,198],{"class":197},[191,2965,2966],{"class":201}," scheduleWork",[191,2968,206],{"class":205},[191,2970,2971,2973],{"class":193,"line":209},[191,2972,212],{"class":197},[191,2974,215],{"class":205},[191,2976,2977,2980,2983,2986],{"class":193,"line":218},[191,2978,2979],{"class":201},"    setTimeout",[191,2981,2982],{"class":205},"(() ",[191,2984,2985],{"class":197},"=>",[191,2987,215],{"class":205},[191,2989,2990,2993,2995,2997,2999,3002],{"class":193,"line":231},[191,2991,2992],{"class":197},"      throw",[191,2994,400],{"class":197},[191,2996,403],{"class":201},[191,2998,278],{"class":205},[191,3000,3001],{"class":224},"\"boom\"",[191,3003,411],{"class":205},[191,3005,3006,3009,3012],{"class":193,"line":241},[191,3007,3008],{"class":205},"    }, ",[191,3010,3011],{"class":604},"100",[191,3013,411],{"class":205},[191,3015,3016,3018,3020],{"class":193,"line":251},[191,3017,234],{"class":205},[191,3019,66],{"class":197},[191,3021,892],{"class":205},[191,3023,3024,3026,3028,3030,3032],{"class":193,"line":257},[191,3025,913],{"class":205},[191,3027,275],{"class":201},[191,3029,278],{"class":205},[191,3031,1960],{"class":224},[191,3033,1277],{"class":205},[191,3035,3036],{"class":193,"line":263},[191,3037,254],{"class":205},[191,3039,3040],{"class":193,"line":269},[191,3041,260],{"class":205},[191,3043,3044],{"class":193,"line":884},[191,3045,266],{"emptyLinePlaceholder":43},[191,3047,3048,3050],{"class":193,"line":895},[191,3049,2952],{"class":201},[191,3051,3052],{"class":205},"();\n",[31,3054,3056,3062,3074,3083],{"className":3055},[34],[36,3057,3059,3061],{"className":3058},[39],[41,3060],{"disabled":43,"type":44}," \"caught: boom\" is logged after 100ms",[36,3063,3065,1294,3067,3069,3070,3073],{"className":3064},[39],[41,3066],{"disabled":43,"type":44},[22,3068,2045],{}," prevents ",[22,3071,3072],{},"setTimeout"," from ever calling the callback",[36,3075,3077,3079,3080,3082],{"className":3076},[39],[41,3078],{"disabled":43,"type":44}," Nothing is logged by the ",[22,3081,66],{},"; the error becomes an uncaught exception once the timer callback runs, in a later turn of the event loop",[36,3084,3086,306,3088,3090,3091,3093,3094,3096],{"className":3085},[39],[41,3087],{"disabled":43,"type":44},[22,3089,486],{}," is thrown immediately because you cannot ",[22,3092,144],{}," inside a ",[22,3095,3072],{}," callback",[100,3098,3099,3101,3108],{},[103,3100,105],{},[107,3102,3103,3105,3106,3082],{},[110,3104,112],{}," C — Nothing is logged by the ",[22,3107,66],{},[107,3109,3110,45,3112,3114,3115,3117,3118,3120,3121,3123,3124,3126,3127],{},[110,3111,130],{},[22,3113,2045],{}," can only catch synchronous exceptions that occur while it's actively on the call stack. ",[22,3116,3072],{}," schedules its callback to run later, in a completely separate event-loop turn — by the time it executes, the original ",[22,3119,2045],{}," has already finished and is off the stack, so it has no way to intercept the throw. The error surfaces as an uncaught exception (Node) or via ",[22,3122,2885],{}," (browsers). The fix is to put the ",[22,3125,2045],{}," inside the callback itself. ",[110,3128,364],{},[14,3130,3131,3142,3251,3288],{"language":174},[17,3132,3134,3135,3138,3139,1831],{"id":3133},"q17-if-saveitem-rejects-for-one-item-what-happens-when-processall-runs","Q17. If ",[22,3136,3137],{},"save(item)"," rejects for one item, what happens when ",[22,3140,3141],{},"processAll",[180,3143,3144],{"language":174},[183,3145,3147],{"className":185,"code":3146,"language":174,"meta":187,"style":187},"async function processAll(items) {\n  try {\n    items.forEach(async (item) => {\n      await save(item);\n    });\n    console.log(\"all done\");\n  } catch (err) {\n    console.log(\"caught:\", err.message);\n  }\n}\n",[22,3148,3149,3165,3171,3194,3205,3210,3223,3231,3243,3247],{"__ignoreMap":187},[191,3150,3151,3153,3155,3158,3160,3163],{"class":193,"line":194},[191,3152,1221],{"class":197},[191,3154,1224],{"class":197},[191,3156,3157],{"class":201}," processAll",[191,3159,278],{"class":205},[191,3161,3162],{"class":590},"items",[191,3164,599],{"class":205},[191,3166,3167,3169],{"class":193,"line":209},[191,3168,212],{"class":197},[191,3170,215],{"class":205},[191,3172,3173,3176,3179,3181,3183,3185,3188,3190,3192],{"class":193,"line":218},[191,3174,3175],{"class":205},"    items.",[191,3177,3178],{"class":201},"forEach",[191,3180,278],{"class":205},[191,3182,1221],{"class":197},[191,3184,836],{"class":205},[191,3186,3187],{"class":590},"item",[191,3189,1657],{"class":205},[191,3191,2985],{"class":197},[191,3193,215],{"class":205},[191,3195,3196,3199,3202],{"class":193,"line":231},[191,3197,3198],{"class":197},"      await",[191,3200,3201],{"class":201}," save",[191,3203,3204],{"class":205},"(item);\n",[191,3206,3207],{"class":193,"line":241},[191,3208,3209],{"class":205},"    });\n",[191,3211,3212,3214,3216,3218,3221],{"class":193,"line":251},[191,3213,913],{"class":205},[191,3215,275],{"class":201},[191,3217,278],{"class":205},[191,3219,3220],{"class":224},"\"all done\"",[191,3222,411],{"class":205},[191,3224,3225,3227,3229],{"class":193,"line":257},[191,3226,234],{"class":205},[191,3228,66],{"class":197},[191,3230,892],{"class":205},[191,3232,3233,3235,3237,3239,3241],{"class":193,"line":263},[191,3234,913],{"class":205},[191,3236,275],{"class":201},[191,3238,278],{"class":205},[191,3240,1960],{"class":224},[191,3242,1277],{"class":205},[191,3244,3245],{"class":193,"line":269},[191,3246,254],{"class":205},[191,3248,3249],{"class":193,"line":884},[191,3250,260],{"class":205},[31,3252,3254,3262,3270,3280],{"className":3253},[34],[36,3255,3257,3259,3260],{"className":3256},[39],[41,3258],{"disabled":43,"type":44}," \"all done\" logs immediately, and the rejection becomes an unhandled promise rejection, uncaught by the surrounding ",[22,3261,2045],{},[36,3263,3265,1294,3267,3269],{"className":3264},[39],[41,3266],{"disabled":43,"type":44},[22,3268,66],{}," block logs the rejection's error message",[36,3271,3273,45,3275,3277,3278],{"className":3272},[39],[41,3274],{"disabled":43,"type":44},[22,3276,3141],{}," itself rejects, and the caller must add a ",[22,3279,2066],{},[36,3281,3283,45,3285,3287],{"className":3282},[39],[41,3284],{"disabled":43,"type":44},[22,3286,3178],{}," waits for all async callbacks to settle before moving to the next line",[100,3289,3290,3292,3299],{},[103,3291,105],{},[107,3293,3294,3296,3297],{},[110,3295,112],{}," A — \"all done\" logs immediately, and the rejection becomes an unhandled promise rejection, uncaught by the surrounding ",[22,3298,2045],{},[107,3300,3301,45,3303,3306,3307,3309,3310,3313,3314,3316,3317,3320,3321,3323,3324,2060,3327,546,3329,549,3332],{},[110,3302,130],{},[22,3304,3305],{},"Array.prototype.forEach"," does not await the promises returned by its (async) callback, nor does it propagate their rejections — it fires all callbacks and moves on immediately, so ",[22,3308,3220],{}," logs right away regardless of what ",[22,3311,3312],{},"save"," does. Any rejection inside one of those detached async callbacks becomes an unhandled promise rejection instead of surfacing in the surrounding ",[22,3315,2045],{},". The idiomatic fix is a ",[22,3318,3319],{},"for...of"," loop with ",[22,3322,1315],{},", or ",[22,3325,3326],{},"Promise.all(items.map(item => save(item)))",[22,3328,51],{},[110,3330,3331],{},"Performance",[110,3333,364],{},[14,3335,3336,3340,3370],{},[17,3337,3339],{"id":3338},"q18-a-function-three-layers-deep-in-a-call-stack-fails-to-write-to-a-cache-a-non-critical-recoverable-failure-while-a-top-level-function-fails-to-authenticate-a-user-a-critical-failure-the-caller-must-react-to-whats-the-best-practice-approach-to-where-each-error-is-caught","Q18. A function three layers deep in a call stack fails to write to a cache (a non-critical, recoverable failure), while a top-level function fails to authenticate a user (a critical failure the caller must react to). What's the best-practice approach to where each error is caught?",[31,3341,3343,3349,3355,3361],{"className":3342},[34],[36,3344,3346,3348],{"className":3345},[39],[41,3347],{"disabled":43,"type":44}," Catch both errors at the very top of the application in a single global handler, to keep error-handling logic centralized",[36,3350,3352,3354],{"className":3351},[39],[41,3353],{"disabled":43,"type":44}," Never catch errors inside deeply nested functions; always let every error bubble to the top",[36,3356,3358,3360],{"className":3357},[39],[41,3359],{"disabled":43,"type":44}," Catch every error immediately where it's thrown and never rethrow, to avoid unhandled rejections",[36,3362,3364,3366,3367,3369],{"className":3363},[39],[41,3365],{"disabled":43,"type":44}," Catch the cache-write failure close to where it happens (a fallback, like skipping the cache, is possible there), and let the authentication failure propagate up to a caller that can actually decide what to do, attaching context via ",[22,3368,1546],{}," or custom fields as it goes",[100,3371,3372,3374,3381],{},[103,3373,105],{},[107,3375,3376,3378,3379,3369],{},[110,3377,112],{}," D — Catch the cache-write failure close to where it happens, and let the authentication failure propagate up to a caller that can actually decide what to do, attaching context via ",[22,3380,1546],{},[107,3382,3383,3385,3386,3388,3389],{},[110,3384,130],{}," The right layer to catch an error is the layer that can do something meaningful about it. A recoverable, local failure (skip the cache, continue) should be handled where the fallback is known; a failure that requires a caller-level decision (redirect to login, retry, surface to the user) should propagate — ideally enriched with ",[22,3387,1546],{}," or extra fields at each hop — rather than being caught prematurely and silently discarded. A centralizes logic but loses recovery opportunities; C swallows everything, hiding real failures from callers who need to know. ",[110,3390,1363],{},[14,3392,3393,3397,3539,3566],{"language":174},[17,3394,3396],{"id":3395},"q19-what-does-this-log","Q19. What does this log?",[180,3398,3399],{"language":174},[183,3400,3402],{"className":185,"code":3401,"language":174,"meta":187,"style":187},"function transferFunds(amount) {\n  try {\n    throw new Error(\"insufficient balance\");\n  } finally {\n    validateAudit();\n  }\n}\n\nfunction validateAudit() {\n  throw new Error(\"audit log unavailable\");\n}\n\ntry {\n  transferFunds(100);\n} catch (err) {\n  console.log(err.message);\n}\n",[22,3403,3404,3418,3424,3439,3447,3454,3458,3462,3466,3475,3491,3495,3499,3505,3516,3524,3534],{"__ignoreMap":187},[191,3405,3406,3408,3411,3413,3416],{"class":193,"line":194},[191,3407,198],{"class":197},[191,3409,3410],{"class":201}," transferFunds",[191,3412,278],{"class":205},[191,3414,3415],{"class":590},"amount",[191,3417,599],{"class":205},[191,3419,3420,3422],{"class":193,"line":209},[191,3421,212],{"class":197},[191,3423,215],{"class":205},[191,3425,3426,3428,3430,3432,3434,3437],{"class":193,"line":218},[191,3427,397],{"class":197},[191,3429,400],{"class":197},[191,3431,403],{"class":201},[191,3433,278],{"class":205},[191,3435,3436],{"class":224},"\"insufficient balance\"",[191,3438,411],{"class":205},[191,3440,3441,3443,3445],{"class":193,"line":231},[191,3442,234],{"class":205},[191,3444,24],{"class":197},[191,3446,215],{"class":205},[191,3448,3449,3452],{"class":193,"line":241},[191,3450,3451],{"class":201},"    validateAudit",[191,3453,3052],{"class":205},[191,3455,3456],{"class":193,"line":251},[191,3457,254],{"class":205},[191,3459,3460],{"class":193,"line":257},[191,3461,260],{"class":205},[191,3463,3464],{"class":193,"line":263},[191,3465,266],{"emptyLinePlaceholder":43},[191,3467,3468,3470,3473],{"class":193,"line":269},[191,3469,198],{"class":197},[191,3471,3472],{"class":201}," validateAudit",[191,3474,206],{"class":205},[191,3476,3477,3480,3482,3484,3486,3489],{"class":193,"line":884},[191,3478,3479],{"class":197},"  throw",[191,3481,400],{"class":197},[191,3483,403],{"class":201},[191,3485,278],{"class":205},[191,3487,3488],{"class":224},"\"audit log unavailable\"",[191,3490,411],{"class":205},[191,3492,3493],{"class":193,"line":895},[191,3494,260],{"class":205},[191,3496,3497],{"class":193,"line":910},[191,3498,266],{"emptyLinePlaceholder":43},[191,3500,3501,3503],{"class":193,"line":932},[191,3502,51],{"class":197},[191,3504,215],{"class":205},[191,3506,3507,3510,3512,3514],{"class":193,"line":937},[191,3508,3509],{"class":201},"  transferFunds",[191,3511,278],{"class":205},[191,3513,3011],{"class":604},[191,3515,411],{"class":205},[191,3517,3518,3520,3522],{"class":193,"line":1495},[191,3519,887],{"class":205},[191,3521,66],{"class":197},[191,3523,892],{"class":205},[191,3525,3527,3529,3531],{"class":193,"line":3526},16,[191,3528,1706],{"class":205},[191,3530,275],{"class":201},[191,3532,3533],{"class":205},"(err.message);\n",[191,3535,3537],{"class":193,"line":3536},17,[191,3538,260],{"class":205},[31,3540,3542,3548,3554,3560],{"className":3541},[34],[36,3543,3545,3547],{"className":3544},[39],[41,3546],{"disabled":43,"type":44}," \"audit log unavailable\" is logged, and \"insufficient balance\" is discarded entirely",[36,3549,3551,3553],{"className":3550},[39],[41,3552],{"disabled":43,"type":44}," \"insufficient balance\" is logged",[36,3555,3557,3559],{"className":3556},[39],[41,3558],{"disabled":43,"type":44}," Both error messages are logged, joined together",[36,3561,3563,3565],{"className":3562},[39],[41,3564],{"disabled":43,"type":44}," Nothing is logged because two errors in one call stack crash the process",[100,3567,3568,3570,3575],{},[103,3569,105],{},[107,3571,3572,3574],{},[110,3573,112],{}," A — \"audit log unavailable\" is logged, and \"insufficient balance\" is discarded entirely",[107,3576,3577,3579,3580,496,3582,3584,3585,3587,3588,63,3590,3592,3593,3595,3596,2471,3598,3600,3601,3604,3605,3607,3608,3610,3611,549,3613],{},[110,3578,130],{}," Just as an explicit ",[22,3581,76],{},[22,3583,24],{}," overrides a pending return or throw, a new exception thrown inside ",[22,3586,24],{}," also overrides whatever was propagating from ",[22,3589,51],{},[22,3591,66],{}," — ",[22,3594,3436],{}," never reaches the outer ",[22,3597,66],{},[22,3599,24],{},"'s own ",[22,3602,3603],{},"throw new Error(\"audit log unavailable\")"," replaces it as the statement's outcome. This is why code inside ",[22,3606,24],{}," should be simple and defensive (or wrapped in its own ",[22,3609,2045],{},") — an unrelated failure there can silently mask the real error. ",[110,3612,364],{},[110,3614,552],{},[14,3616,3617,3621,3713,3772],{"language":174},[17,3618,3620],{"id":3619},"q20-which-statement-best-describes-why-this-implementation-follows-good-error-handling-practice","Q20. Which statement best describes why this implementation follows good error-handling practice?",[180,3622,3623],{"language":174},[183,3624,3626],{"className":185,"code":3625,"language":174,"meta":187,"style":187},"async function loadSettings(raw) {\n  try {\n    const parsed = JSON.parse(raw);\n    return await applyDefaults(parsed);\n  } catch (err) {\n    throw new Error(\"could not load settings\", { cause: err });\n  }\n}\n",[22,3627,3628,3644,3650,3670,3682,3690,3705,3709],{"__ignoreMap":187},[191,3629,3630,3632,3634,3637,3639,3642],{"class":193,"line":194},[191,3631,1221],{"class":197},[191,3633,1224],{"class":197},[191,3635,3636],{"class":201}," loadSettings",[191,3638,278],{"class":205},[191,3640,3641],{"class":590},"raw",[191,3643,599],{"class":205},[191,3645,3646,3648],{"class":193,"line":209},[191,3647,212],{"class":197},[191,3649,215],{"class":205},[191,3651,3652,3655,3658,3660,3663,3665,3667],{"class":193,"line":218},[191,3653,3654],{"class":197},"    const",[191,3656,3657],{"class":604}," parsed",[191,3659,649],{"class":197},[191,3661,3662],{"class":604}," JSON",[191,3664,2532],{"class":205},[191,3666,2535],{"class":201},[191,3668,3669],{"class":205},"(raw);\n",[191,3671,3672,3674,3676,3679],{"class":193,"line":231},[191,3673,221],{"class":197},[191,3675,2339],{"class":197},[191,3677,3678],{"class":201}," applyDefaults",[191,3680,3681],{"class":205},"(parsed);\n",[191,3683,3684,3686,3688],{"class":193,"line":241},[191,3685,234],{"class":205},[191,3687,66],{"class":197},[191,3689,892],{"class":205},[191,3691,3692,3694,3696,3698,3700,3703],{"class":193,"line":251},[191,3693,397],{"class":197},[191,3695,400],{"class":197},[191,3697,403],{"class":201},[191,3699,278],{"class":205},[191,3701,3702],{"class":224},"\"could not load settings\"",[191,3704,2371],{"class":205},[191,3706,3707],{"class":193,"line":257},[191,3708,254],{"class":205},[191,3710,3711],{"class":193,"line":263},[191,3712,260],{"class":205},[31,3714,3716,3731,3743,3762],{"className":3715},[34],[36,3717,3719,3721,3722,3724,3725,3727,3728,3730],{"className":3718},[39],[41,3720],{"disabled":43,"type":44}," It is flawed because ",[22,3723,2045],{}," cannot wrap both a synchronous call (",[22,3726,2670],{},") and an ",[22,3729,1315],{}," expression in the same block",[36,3732,3734,3736,3737,3739,3740,3742],{"className":3733},[39],[41,3735],{"disabled":43,"type":44}," It is flawed because throwing inside a ",[22,3738,66],{}," block is not allowed in ",[22,3741,1221],{}," functions",[36,3744,3746,3748,3749,3751,3752,3754,3755,3758,3759,3761],{"className":3745},[39],[41,3747],{"disabled":43,"type":44}," It catches both the potential ",[22,3750,309],{}," from ",[22,3753,2670],{}," and any rejection from ",[22,3756,3757],{},"applyDefaults"," in a single block, wraps them in a descriptive higher-level error, and preserves the original failure via ",[22,3760,1546],{}," — all without swallowing it",[36,3763,3765,3767,3768,3771],{"className":3764},[39],[41,3766],{"disabled":43,"type":44}," It should use ",[22,3769,3770],{},"catch {}"," with no binding, since the original error is discarded anyway",[100,3773,3774,3776,3789],{},[103,3775,105],{},[107,3777,3778,3780,3781,3751,3783,3754,3785,3758,3787,3761],{},[110,3779,112],{}," C — It catches both the potential ",[22,3782,309],{},[22,3784,2670],{},[22,3786,3757],{},[22,3788,1546],{},[107,3790,3791,3793,3794,3796,3797,3799,3800,3802,3803,3806,3807,3809,3810,3812,3813],{},[110,3792,130],{}," A single ",[22,3795,51],{}," can legally mix synchronous statements and ",[22,3798,1315],{},"ed expressions — either kind of failure lands in the same ",[22,3801,66],{},". Wrapping with a clearer message while attaching ",[22,3804,3805],{},"{ cause: err }"," gives callers a readable error and preserves the root cause for logs and debuggers, rather than either swallowing the original error or leaking a raw ",[22,3808,309],{},"\u002Frejection with no context. A and B describe restrictions that don't exist in JS; D is wrong because the original error is deliberately preserved via ",[22,3811,1546],{},", not discarded. ",[110,3814,1363],{},[3816,3817,3818],"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 .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);}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}",{"title":187,"searchDepth":209,"depth":209,"links":3820},[3821,3823,3824,3825,3826,3827,3828,3829,3830,3831,3833,3835,3836,3837,3838,3840,3842,3844,3845,3846],{"id":19,"depth":218,"text":3822},"Q1. Which statement about the finally block in a try\u002Fcatch\u002Ffinally statement is true?",{"id":177,"depth":218,"text":178},{"id":369,"depth":218,"text":370},{"id":557,"depth":218,"text":558},{"id":776,"depth":218,"text":777},{"id":1031,"depth":218,"text":1032},{"id":1208,"depth":218,"text":1209},{"id":1368,"depth":218,"text":1369},{"id":1619,"depth":218,"text":1620},{"id":1826,"depth":218,"text":3832},"Q10. What happens when handleRequest runs?",{"id":2073,"depth":218,"text":3834},"Q11. What happens if the request inside fetchProfile fails?",{"id":2303,"depth":218,"text":2304},{"id":2510,"depth":218,"text":2511},{"id":2726,"depth":218,"text":2727},{"id":2881,"depth":218,"text":3839},"Q15. Why are window.onerror and the unhandledrejection event described as \"last resort\" global error handlers rather than a replacement for local try\u002Fcatch?",{"id":2948,"depth":218,"text":3841},"Q16. What happens when scheduleWork runs?",{"id":3133,"depth":218,"text":3843},"Q17. If save(item) rejects for one item, what happens when processAll runs?",{"id":3338,"depth":218,"text":3339},{"id":3395,"depth":218,"text":3396},{"id":3619,"depth":218,"text":3620},"md",{},"\u002Fjs\u002F18-error-handling",{"title":5,"description":187},"js\u002F18-error-handling","cKRRdjFMLTcaogDw96bxS9KvtRm-ZB-UZDJEqIpMr88",1787335397335]