[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Ferror":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Ferror":1912,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Ferror":1938},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":1908,"stem":1909,"id":1910,"extension":1911},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Ferror","错误处理与健壮性","构建健壮的 Node.js 应用，必须系统性地处理各种错误，包括同步、异步、未捕获异常等，并结合进程管理和健康检查保证服务可用性。","技能小册",[12,13],"nodejs","error","2021-01-24",false,{"type":17,"value":18,"toc":1898},"minimark",[19,22,27,30,35,43,154,161,331,334,372,376,385,469,478,482,491,563,577,694,700,802,806,812,830,924,934,941,952,1047,1061,1065,1071,1180,1183,1237,1243,1247,1250,1254,1357,1364,1551,1555,1562,1642,1645,1669,1673,1679,1820,1823,1827,1891,1894],[20,21,8],"h1",{"id":8},[23,24,26],"h2",{"id":25},"nodejs-错误处理与健壮性","Node.js 错误处理与健壮性",[28,29,9],"p",{},[31,32,34],"h3",{"id":33},"一错误类型","一、错误类型",[28,36,37,38,42],{},"Node.js 内置了多种错误构造函数，所有错误都继承自 ",[39,40,41],"code",{},"Error","。",[44,45,46,62],"table",{},[47,48,49],"thead",{},[50,51,52,56,59],"tr",{},[53,54,55],"th",{},"类型",[53,57,58],{},"描述",[53,60,61],{},"常见场景",[63,64,65,78,95,108,125,138],"tbody",{},[50,66,67,72,75],{},[68,69,70],"td",{},[39,71,41],{},[68,73,74],{},"通用错误",[68,76,77],{},"主动抛出的未知错误",[50,79,80,85,88],{},[68,81,82],{},[39,83,84],{},"TypeError",[68,86,87],{},"参数类型不符合预期",[68,89,90,91,94],{},"调用非函数、读取 ",[39,92,93],{},"null"," 属性",[50,96,97,102,105],{},[68,98,99],{},[39,100,101],{},"RangeError",[68,103,104],{},"数值超出有效范围",[68,106,107],{},"数组长度负值、递归栈溢出",[50,109,110,115,118],{},[68,111,112],{},[39,113,114],{},"SyntaxError",[68,116,117],{},"语法错误（通常发生在启动解析阶段）",[68,119,120,121,124],{},"代码书写错误（",[39,122,123],{},"eval"," 也可能触发）",[50,126,127,132,135],{},[68,128,129],{},[39,130,131],{},"ReferenceError",[68,133,134],{},"引用未声明变量",[68,136,137],{},"访问未定义的变量",[50,139,140,145,148],{},[68,141,142],{},[39,143,144],{},"URIError",[68,146,147],{},"全局 URI 处理函数错误",[68,149,150,153],{},[39,151,152],{},"decodeURI"," 传入非法字符串",[28,155,156,160],{},[157,158,159],"strong",{},"自定义 AppError","：为业务错误统一结构，便于分类处理。",[162,163,168],"pre",{"className":164,"code":165,"language":166,"meta":167,"style":167},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","class AppError extends Error {\n    constructor(message, statusCode, isOperational = true) {\n        super(message);\n        this.statusCode = statusCode;\n        this.isOperational = isOperational; \u002F\u002F 区分可恢复错误 vs 程序缺陷\n        Error.captureStackTrace(this, this.constructor);\n    }\n}\n","js","",[39,169,170,193,230,248,267,288,319,325],{"__ignoreMap":167},[171,172,175,179,183,186,189],"span",{"class":173,"line":174},"line",1,[171,176,178],{"class":177},"sbsja","class",[171,180,182],{"class":181},"sbgvK"," AppError",[171,184,185],{"class":177}," extends",[171,187,188],{"class":181}," Error",[171,190,192],{"class":191},"sP7_E"," {\n",[171,194,196,199,202,206,209,212,214,217,221,225,228],{"class":173,"line":195},2,[171,197,198],{"class":177},"    constructor",[171,200,201],{"class":191},"(",[171,203,205],{"class":204},"s99_P","message",[171,207,208],{"class":191},",",[171,210,211],{"class":204}," statusCode",[171,213,208],{"class":191},[171,215,216],{"class":204}," isOperational",[171,218,220],{"class":219},"smGrS"," =",[171,222,224],{"class":223},"syTEX"," true",[171,226,227],{"class":191},")",[171,229,192],{"class":191},[171,231,233,237,240,243,245],{"class":173,"line":232},3,[171,234,236],{"class":235},"s_hVV","        super",[171,238,201],{"class":239},"skxfh",[171,241,205],{"class":242},"su5hD",[171,244,227],{"class":239},[171,246,247],{"class":191},";\n",[171,249,251,255,258,261,263,265],{"class":173,"line":250},4,[171,252,254],{"class":253},"s39Yj","        this",[171,256,257],{"class":191},".",[171,259,260],{"class":242},"statusCode",[171,262,220],{"class":219},[171,264,211],{"class":242},[171,266,247],{"class":191},[171,268,270,272,274,277,279,281,284],{"class":173,"line":269},5,[171,271,254],{"class":253},[171,273,257],{"class":191},[171,275,276],{"class":242},"isOperational",[171,278,220],{"class":219},[171,280,216],{"class":242},[171,282,283],{"class":191},";",[171,285,287],{"class":286},"sutJx"," \u002F\u002F 区分可恢复错误 vs 程序缺陷\n",[171,289,291,294,296,300,302,305,307,310,312,315,317],{"class":173,"line":290},6,[171,292,293],{"class":242},"        Error",[171,295,257],{"class":191},[171,297,299],{"class":298},"sGLFI","captureStackTrace",[171,301,201],{"class":239},[171,303,304],{"class":253},"this",[171,306,208],{"class":191},[171,308,309],{"class":253}," this",[171,311,257],{"class":191},[171,313,314],{"class":235},"constructor",[171,316,227],{"class":239},[171,318,247],{"class":191},[171,320,322],{"class":173,"line":321},7,[171,323,324],{"class":191},"    }\n",[171,326,328],{"class":173,"line":327},8,[171,329,330],{"class":191},"}\n",[28,332,333],{},"使用示例：",[162,335,337],{"className":164,"code":336,"language":166,"meta":167,"style":167},"throw new AppError(\"用户不存在\", 404);\n",[39,338,339],{"__ignoreMap":167},[171,340,341,345,348,350,352,356,360,362,364,368,370],{"class":173,"line":174},[171,342,344],{"class":343},"sVHd0","throw",[171,346,347],{"class":219}," new",[171,349,182],{"class":298},[171,351,201],{"class":242},[171,353,355],{"class":354},"sjJ54","\"",[171,357,359],{"class":358},"s_sjI","用户不存在",[171,361,355],{"class":354},[171,363,208],{"class":191},[171,365,367],{"class":366},"srdBf"," 404",[171,369,227],{"class":242},[171,371,247],{"class":191},[31,373,375],{"id":374},"二同步与异步错误捕获","二、同步与异步错误捕获",[377,378,380,381,384],"h4",{"id":379},"_1-trycatch-仅适用于同步代码","1. ",[39,382,383],{},"try\u002Fcatch"," 仅适用于同步代码",[162,386,388],{"className":164,"code":387,"language":166,"meta":167,"style":167},"try {\n    JSON.parse(\"invalid json\");\n} catch (err) {\n    console.error(\"同步错误已捕获\", err.message);\n}\n",[39,389,390,397,420,434,465],{"__ignoreMap":167},[171,391,392,395],{"class":173,"line":174},[171,393,394],{"class":343},"try",[171,396,192],{"class":191},[171,398,399,402,404,407,409,411,414,416,418],{"class":173,"line":195},[171,400,401],{"class":235},"    JSON",[171,403,257],{"class":191},[171,405,406],{"class":298},"parse",[171,408,201],{"class":239},[171,410,355],{"class":354},[171,412,413],{"class":358},"invalid json",[171,415,355],{"class":354},[171,417,227],{"class":239},[171,419,247],{"class":191},[171,421,422,425,428,431],{"class":173,"line":232},[171,423,424],{"class":191},"}",[171,426,427],{"class":343}," catch",[171,429,430],{"class":242}," (err) ",[171,432,433],{"class":191},"{\n",[171,435,436,439,441,443,445,447,450,452,454,457,459,461,463],{"class":173,"line":250},[171,437,438],{"class":242},"    console",[171,440,257],{"class":191},[171,442,13],{"class":298},[171,444,201],{"class":239},[171,446,355],{"class":354},[171,448,449],{"class":358},"同步错误已捕获",[171,451,355],{"class":354},[171,453,208],{"class":191},[171,455,456],{"class":242}," err",[171,458,257],{"class":191},[171,460,205],{"class":242},[171,462,227],{"class":239},[171,464,247],{"class":191},[171,466,467],{"class":173,"line":269},[171,468,330],{"class":191},[28,470,471,472,474,475,477],{},"对于异步回调中的错误，",[39,473,383],{}," 无法捕获，因为回调执行时 ",[39,476,394],{}," 块已结束。",[377,479,481],{"id":480},"_2-异步错误捕获方法","2. 异步错误捕获方法",[28,483,484,487,488,42],{},[157,485,486],{},"Promise 链","：必须添加 ",[39,489,490],{},".catch()",[162,492,494],{"className":164,"code":493,"language":166,"meta":167,"style":167},"doSomethingAsync()\n    .then(result => process(result))\n    .catch(err => console.error(\"Promise 错误:\", err));\n",[39,495,496,504,526],{"__ignoreMap":167},[171,497,498,501],{"class":173,"line":174},[171,499,500],{"class":298},"doSomethingAsync",[171,502,503],{"class":242},"()\n",[171,505,506,509,512,514,517,520,523],{"class":173,"line":195},[171,507,508],{"class":191},"    .",[171,510,511],{"class":298},"then",[171,513,201],{"class":242},[171,515,516],{"class":204},"result",[171,518,519],{"class":177}," =>",[171,521,522],{"class":298}," process",[171,524,525],{"class":242},"(result))\n",[171,527,528,530,533,535,538,540,543,545,547,549,551,554,556,558,561],{"class":173,"line":232},[171,529,508],{"class":191},[171,531,532],{"class":298},"catch",[171,534,201],{"class":242},[171,536,537],{"class":204},"err",[171,539,519],{"class":177},[171,541,542],{"class":242}," console",[171,544,257],{"class":191},[171,546,13],{"class":298},[171,548,201],{"class":242},[171,550,355],{"class":354},[171,552,553],{"class":358},"Promise 错误:",[171,555,355],{"class":354},[171,557,208],{"class":191},[171,559,560],{"class":242}," err))",[171,562,247],{"class":191},[28,564,565,570,571,573,574,42],{},[157,566,567],{},[39,568,569],{},"async\u002Fawait","：使用 ",[39,572,383],{}," 包裹 ",[39,575,576],{},"await",[162,578,580],{"className":164,"code":579,"language":166,"meta":167,"style":167},"async function run() {\n    try {\n        const data = await fetchData();\n        console.log(data);\n    } catch (err) {\n        console.error(\"async 错误:\", err);\n    }\n}\n",[39,581,582,598,605,625,644,661,686,690],{"__ignoreMap":167},[171,583,584,587,590,593,596],{"class":173,"line":174},[171,585,586],{"class":177},"async",[171,588,589],{"class":177}," function",[171,591,592],{"class":298}," run",[171,594,595],{"class":191},"()",[171,597,192],{"class":191},[171,599,600,603],{"class":173,"line":195},[171,601,602],{"class":343},"    try",[171,604,192],{"class":191},[171,606,607,610,613,615,618,621,623],{"class":173,"line":232},[171,608,609],{"class":177},"        const",[171,611,612],{"class":235}," data",[171,614,220],{"class":219},[171,616,617],{"class":343}," await",[171,619,620],{"class":298}," fetchData",[171,622,595],{"class":239},[171,624,247],{"class":191},[171,626,627,630,632,635,637,640,642],{"class":173,"line":250},[171,628,629],{"class":242},"        console",[171,631,257],{"class":191},[171,633,634],{"class":298},"log",[171,636,201],{"class":239},[171,638,639],{"class":242},"data",[171,641,227],{"class":239},[171,643,247],{"class":191},[171,645,646,649,651,654,656,659],{"class":173,"line":269},[171,647,648],{"class":191},"    }",[171,650,427],{"class":343},[171,652,653],{"class":239}," (",[171,655,537],{"class":242},[171,657,658],{"class":239},") ",[171,660,433],{"class":191},[171,662,663,665,667,669,671,673,676,678,680,682,684],{"class":173,"line":290},[171,664,629],{"class":242},[171,666,257],{"class":191},[171,668,13],{"class":298},[171,670,201],{"class":239},[171,672,355],{"class":354},[171,674,675],{"class":358},"async 错误:",[171,677,355],{"class":354},[171,679,208],{"class":191},[171,681,456],{"class":242},[171,683,227],{"class":239},[171,685,247],{"class":191},[171,687,688],{"class":173,"line":321},[171,689,324],{"class":191},[171,691,692],{"class":173,"line":327},[171,693,330],{"class":191},[28,695,696,699],{},[157,697,698],{},"回调风格","：错误优先回调的第一个参数为错误对象。",[162,701,703],{"className":164,"code":702,"language":166,"meta":167,"style":167},"fs.readFile(\"file.txt\", (err, data) => {\n    if (err) {\n        console.error(\"读取失败\", err);\n        return;\n    }\n    \u002F\u002F 处理 data\n});\n",[39,704,705,740,753,778,785,789,794],{"__ignoreMap":167},[171,706,707,710,712,715,717,719,722,724,726,728,730,732,734,736,738],{"class":173,"line":174},[171,708,709],{"class":242},"fs",[171,711,257],{"class":191},[171,713,714],{"class":298},"readFile",[171,716,201],{"class":242},[171,718,355],{"class":354},[171,720,721],{"class":358},"file.txt",[171,723,355],{"class":354},[171,725,208],{"class":191},[171,727,653],{"class":191},[171,729,537],{"class":204},[171,731,208],{"class":191},[171,733,612],{"class":204},[171,735,227],{"class":191},[171,737,519],{"class":177},[171,739,192],{"class":191},[171,741,742,745,747,749,751],{"class":173,"line":195},[171,743,744],{"class":343},"    if",[171,746,653],{"class":239},[171,748,537],{"class":242},[171,750,658],{"class":239},[171,752,433],{"class":191},[171,754,755,757,759,761,763,765,768,770,772,774,776],{"class":173,"line":232},[171,756,629],{"class":242},[171,758,257],{"class":191},[171,760,13],{"class":298},[171,762,201],{"class":239},[171,764,355],{"class":354},[171,766,767],{"class":358},"读取失败",[171,769,355],{"class":354},[171,771,208],{"class":191},[171,773,456],{"class":242},[171,775,227],{"class":239},[171,777,247],{"class":191},[171,779,780,783],{"class":173,"line":250},[171,781,782],{"class":343},"        return",[171,784,247],{"class":191},[171,786,787],{"class":173,"line":269},[171,788,324],{"class":191},[171,790,791],{"class":173,"line":290},[171,792,793],{"class":286},"    \u002F\u002F 处理 data\n",[171,795,796,798,800],{"class":173,"line":321},[171,797,424],{"class":191},[171,799,227],{"class":242},[171,801,247],{"class":191},[31,803,805],{"id":804},"三全局未捕获异常","三、全局未捕获异常",[377,807,380,809],{"id":808},"_1-processonuncaughtexception",[39,810,811],{},"process.on('uncaughtException')",[28,813,814,815,817,818,821,822,825,826,829],{},"该事件用于捕获未在 ",[39,816,383],{}," 或 ",[39,819,820],{},".catch"," 中处理的同步\u002F异步错误（例如 ",[39,823,824],{},"setTimeout"," 里的同步错误、未捕获的异常）。",[157,827,828],{},"它只是最后防线","，不应依赖它来维持应用正常运行，因为出错后应用可能处于不一致状态。",[162,831,833],{"className":164,"code":832,"language":166,"meta":167,"style":167},"process.on(\"uncaughtException\", err => {\n    console.error(\"未捕获异常:\", err);\n    \u002F\u002F 执行清理逻辑（关闭数据库连接、服务器等）\n    \u002F\u002F 然后优雅退出\n    process.exit(1);\n});\n",[39,834,835,862,887,892,897,916],{"__ignoreMap":167},[171,836,837,840,842,845,847,849,852,854,856,858,860],{"class":173,"line":174},[171,838,839],{"class":242},"process",[171,841,257],{"class":191},[171,843,844],{"class":298},"on",[171,846,201],{"class":242},[171,848,355],{"class":354},[171,850,851],{"class":358},"uncaughtException",[171,853,355],{"class":354},[171,855,208],{"class":191},[171,857,456],{"class":204},[171,859,519],{"class":177},[171,861,192],{"class":191},[171,863,864,866,868,870,872,874,877,879,881,883,885],{"class":173,"line":195},[171,865,438],{"class":242},[171,867,257],{"class":191},[171,869,13],{"class":298},[171,871,201],{"class":239},[171,873,355],{"class":354},[171,875,876],{"class":358},"未捕获异常:",[171,878,355],{"class":354},[171,880,208],{"class":191},[171,882,456],{"class":242},[171,884,227],{"class":239},[171,886,247],{"class":191},[171,888,889],{"class":173,"line":232},[171,890,891],{"class":286},"    \u002F\u002F 执行清理逻辑（关闭数据库连接、服务器等）\n",[171,893,894],{"class":173,"line":250},[171,895,896],{"class":286},"    \u002F\u002F 然后优雅退出\n",[171,898,899,902,904,907,909,912,914],{"class":173,"line":269},[171,900,901],{"class":242},"    process",[171,903,257],{"class":191},[171,905,906],{"class":298},"exit",[171,908,201],{"class":239},[171,910,911],{"class":366},"1",[171,913,227],{"class":239},[171,915,247],{"class":191},[171,917,918,920,922],{"class":173,"line":290},[171,919,424],{"class":191},[171,921,227],{"class":242},[171,923,247],{"class":191},[28,925,926,929,930,933],{},[157,927,928],{},"最佳实践","：记录错误后立即退出进程（",[39,931,932],{},"process.exit(1)","），并让进程管理器（如 PM2）负责重启。",[377,935,937,938],{"id":936},"_2-processonunhandledrejection","2. ",[39,939,940],{},"process.on('unhandledRejection')",[28,942,943,944,817,946,948,949,951],{},"用于捕获未处理的 Promise 拒绝（没有 ",[39,945,820],{},[39,947,383],{}," 的 ",[39,950,576],{},"）。",[162,953,955],{"className":164,"code":954,"language":166,"meta":167,"style":167},"process.on(\"unhandledRejection\", (reason, promise) => {\n    console.error(\"未处理的 Promise 拒绝:\", reason);\n    \u002F\u002F 可选择退出进程\n    process.exit(1);\n});\n",[39,956,957,992,1018,1023,1039],{"__ignoreMap":167},[171,958,959,961,963,965,967,969,972,974,976,978,981,983,986,988,990],{"class":173,"line":174},[171,960,839],{"class":242},[171,962,257],{"class":191},[171,964,844],{"class":298},[171,966,201],{"class":242},[171,968,355],{"class":354},[171,970,971],{"class":358},"unhandledRejection",[171,973,355],{"class":354},[171,975,208],{"class":191},[171,977,653],{"class":191},[171,979,980],{"class":204},"reason",[171,982,208],{"class":191},[171,984,985],{"class":204}," promise",[171,987,227],{"class":191},[171,989,519],{"class":177},[171,991,192],{"class":191},[171,993,994,996,998,1000,1002,1004,1007,1009,1011,1014,1016],{"class":173,"line":195},[171,995,438],{"class":242},[171,997,257],{"class":191},[171,999,13],{"class":298},[171,1001,201],{"class":239},[171,1003,355],{"class":354},[171,1005,1006],{"class":358},"未处理的 Promise 拒绝:",[171,1008,355],{"class":354},[171,1010,208],{"class":191},[171,1012,1013],{"class":242}," reason",[171,1015,227],{"class":239},[171,1017,247],{"class":191},[171,1019,1020],{"class":173,"line":232},[171,1021,1022],{"class":286},"    \u002F\u002F 可选择退出进程\n",[171,1024,1025,1027,1029,1031,1033,1035,1037],{"class":173,"line":250},[171,1026,901],{"class":242},[171,1028,257],{"class":191},[171,1030,906],{"class":298},[171,1032,201],{"class":239},[171,1034,911],{"class":366},[171,1036,227],{"class":239},[171,1038,247],{"class":191},[171,1040,1041,1043,1045],{"class":173,"line":269},[171,1042,424],{"class":191},[171,1044,227],{"class":242},[171,1046,247],{"class":191},[28,1048,1049,1050,1052,1053,1056,1057,1060],{},"在 Node.js 15+ 中，未处理的拒绝会触发 ",[39,1051,971],{},"，但默认不会终止进程（需要显式 ",[39,1054,1055],{},"process.exit","）。建议配合 ",[39,1058,1059],{},"--unhandled-rejections=strict"," 启动参数，使其直接抛出未捕获异常。",[31,1062,1064],{"id":1063},"四进程退出码","四、进程退出码",[28,1066,1067,1070],{},[39,1068,1069],{},"process.exitCode"," 用于设置进程退出时的状态码，约定如下：",[44,1072,1073,1083],{},[47,1074,1075],{},[50,1076,1077,1080],{},[53,1078,1079],{},"退出码",[53,1081,1082],{},"含义",[63,1084,1085,1093,1100,1108,1116,1128,1136,1144,1152,1160,1168],{},[50,1086,1087,1090],{},[68,1088,1089],{},"0",[68,1091,1092],{},"成功完成",[50,1094,1095,1097],{},[68,1096,911],{},[68,1098,1099],{},"未捕获的错误（通用错误）",[50,1101,1102,1105],{},[68,1103,1104],{},"2",[68,1106,1107],{},"Bash 内置命令使用错误（很少用于 Node）",[50,1109,1110,1113],{},[68,1111,1112],{},"3",[68,1114,1115],{},"内部 JavaScript 解析错误（启动阶段）",[50,1117,1118,1121],{},[68,1119,1120],{},"4",[68,1122,1123,1124,1127],{},"内部执行失败（如 ",[39,1125,1126],{},"EvalError","）",[50,1129,1130,1133],{},[68,1131,1132],{},"5",[68,1134,1135],{},"致命错误（V8 内部断言失败）",[50,1137,1138,1141],{},[68,1139,1140],{},"6",[68,1142,1143],{},"非函数异常处理（事件循环中抛出的异常）",[50,1145,1146,1149],{},[68,1147,1148],{},"7",[68,1150,1151],{},"异常处理时再抛出异常（很少见）",[50,1153,1154,1157],{},[68,1155,1156],{},"9",[68,1158,1159],{},"无效参数",[50,1161,1162,1165],{},[68,1163,1164],{},"12",[68,1166,1167],{},"无效调试参数",[50,1169,1170,1173],{},[68,1171,1172],{},"128 + 信号码",[68,1174,1175,1176,1179],{},"被信号终止（如 ",[39,1177,1178],{},"SIGKILL"," = 128+9=137）",[28,1181,1182],{},"设置方式：",[162,1184,1186],{"className":164,"code":1185,"language":166,"meta":167,"style":167},"\u002F\u002F 方法1：设置 exitCode 并让进程自然退出\nprocess.exitCode = 1;\n\n\u002F\u002F 方法2：立即退出（注意会中断尚未完成的 I\u002FO）\nprocess.exit(1);\n",[39,1187,1188,1193,1210,1216,1221],{"__ignoreMap":167},[171,1189,1190],{"class":173,"line":174},[171,1191,1192],{"class":286},"\u002F\u002F 方法1：设置 exitCode 并让进程自然退出\n",[171,1194,1195,1197,1199,1202,1205,1208],{"class":173,"line":195},[171,1196,839],{"class":242},[171,1198,257],{"class":191},[171,1200,1201],{"class":242},"exitCode ",[171,1203,1204],{"class":219},"=",[171,1206,1207],{"class":366}," 1",[171,1209,247],{"class":191},[171,1211,1212],{"class":173,"line":232},[171,1213,1215],{"emptyLinePlaceholder":1214},true,"\n",[171,1217,1218],{"class":173,"line":250},[171,1219,1220],{"class":286},"\u002F\u002F 方法2：立即退出（注意会中断尚未完成的 I\u002FO）\n",[171,1222,1223,1225,1227,1229,1231,1233,1235],{"class":173,"line":269},[171,1224,839],{"class":242},[171,1226,257],{"class":191},[171,1228,906],{"class":298},[171,1230,201],{"class":242},[171,1232,911],{"class":366},[171,1234,227],{"class":242},[171,1236,247],{"class":191},[28,1238,1239,1240,1242],{},"推荐使用 ",[39,1241,1069],{}," 并让事件循环清空，避免强制退出导致数据丢失。",[31,1244,1246],{"id":1245},"五健康检查与自动重启","五、健康检查与自动重启",[28,1248,1249],{},"生产环境中应使用进程管理器或系统守护工具，实现崩溃自动重启和健康检查。",[377,1251,1253],{"id":1252},"_1-pm2常用-nodejs-进程管理器","1. PM2（常用 Node.js 进程管理器）",[162,1255,1259],{"className":1256,"code":1257,"language":1258,"meta":167,"style":167},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","# 启动应用\npm2 start app.js --name my-app\n\n# 启用自动重启（默认开启）\npm2 start app.js --watch  # 监听文件变化重启\n\n# 设置内存限制，超出自动重启\npm2 start app.js --max-memory-restart 500M\n\n# 查看状态\npm2 list\npm2 monit\n","bash",[39,1260,1261,1266,1284,1288,1293,1307,1311,1316,1330,1335,1341,1349],{"__ignoreMap":167},[171,1262,1263],{"class":173,"line":174},[171,1264,1265],{"class":286},"# 启动应用\n",[171,1267,1268,1271,1274,1277,1281],{"class":173,"line":195},[171,1269,1270],{"class":181},"pm2",[171,1272,1273],{"class":358}," start",[171,1275,1276],{"class":358}," app.js",[171,1278,1280],{"class":1279},"stzsN"," --name",[171,1282,1283],{"class":358}," my-app\n",[171,1285,1286],{"class":173,"line":232},[171,1287,1215],{"emptyLinePlaceholder":1214},[171,1289,1290],{"class":173,"line":250},[171,1291,1292],{"class":286},"# 启用自动重启（默认开启）\n",[171,1294,1295,1297,1299,1301,1304],{"class":173,"line":269},[171,1296,1270],{"class":181},[171,1298,1273],{"class":358},[171,1300,1276],{"class":358},[171,1302,1303],{"class":1279}," --watch",[171,1305,1306],{"class":286},"  # 监听文件变化重启\n",[171,1308,1309],{"class":173,"line":290},[171,1310,1215],{"emptyLinePlaceholder":1214},[171,1312,1313],{"class":173,"line":321},[171,1314,1315],{"class":286},"# 设置内存限制，超出自动重启\n",[171,1317,1318,1320,1322,1324,1327],{"class":173,"line":327},[171,1319,1270],{"class":181},[171,1321,1273],{"class":358},[171,1323,1276],{"class":358},[171,1325,1326],{"class":1279}," --max-memory-restart",[171,1328,1329],{"class":358}," 500M\n",[171,1331,1333],{"class":173,"line":1332},9,[171,1334,1215],{"emptyLinePlaceholder":1214},[171,1336,1338],{"class":173,"line":1337},10,[171,1339,1340],{"class":286},"# 查看状态\n",[171,1342,1344,1346],{"class":173,"line":1343},11,[171,1345,1270],{"class":181},[171,1347,1348],{"class":358}," list\n",[171,1350,1352,1354],{"class":173,"line":1351},12,[171,1353,1270],{"class":181},[171,1355,1356],{"class":358}," monit\n",[28,1358,1359,1360,1363],{},"PM2 会监控进程，当进程退出（非 0 码）时自动重启。可在 ",[39,1361,1362],{},"ecosystem.config.js"," 中配置健康检查：",[162,1365,1367],{"className":164,"code":1366,"language":166,"meta":167,"style":167},"module.exports = {\n    apps: [\n        {\n            name: \"app\",\n            script: \"app.js\",\n            instances: 1,\n            exec_mode: \"fork\",\n            max_memory_restart: \"500M\",\n            \u002F\u002F 自定义健康检查脚本\n            health_check: \"\u002Fhealth\",\n            \u002F\u002F 重启策略\n            min_uptime: \"10s\",\n            max_restarts: 10,\n        },\n    ],\n};\n",[39,1368,1369,1383,1394,1399,1417,1433,1444,1460,1476,1481,1497,1502,1518,1531,1537,1545],{"__ignoreMap":167},[171,1370,1371,1374,1376,1379,1381],{"class":173,"line":174},[171,1372,1373],{"class":253},"module",[171,1375,257],{"class":191},[171,1377,1378],{"class":253},"exports",[171,1380,220],{"class":219},[171,1382,192],{"class":191},[171,1384,1385,1388,1391],{"class":173,"line":195},[171,1386,1387],{"class":239},"    apps",[171,1389,1390],{"class":191},":",[171,1392,1393],{"class":242}," [\n",[171,1395,1396],{"class":173,"line":232},[171,1397,1398],{"class":191},"        {\n",[171,1400,1401,1404,1406,1409,1412,1414],{"class":173,"line":250},[171,1402,1403],{"class":239},"            name",[171,1405,1390],{"class":191},[171,1407,1408],{"class":354}," \"",[171,1410,1411],{"class":358},"app",[171,1413,355],{"class":354},[171,1415,1416],{"class":191},",\n",[171,1418,1419,1422,1424,1426,1429,1431],{"class":173,"line":269},[171,1420,1421],{"class":239},"            script",[171,1423,1390],{"class":191},[171,1425,1408],{"class":354},[171,1427,1428],{"class":358},"app.js",[171,1430,355],{"class":354},[171,1432,1416],{"class":191},[171,1434,1435,1438,1440,1442],{"class":173,"line":290},[171,1436,1437],{"class":239},"            instances",[171,1439,1390],{"class":191},[171,1441,1207],{"class":366},[171,1443,1416],{"class":191},[171,1445,1446,1449,1451,1453,1456,1458],{"class":173,"line":321},[171,1447,1448],{"class":239},"            exec_mode",[171,1450,1390],{"class":191},[171,1452,1408],{"class":354},[171,1454,1455],{"class":358},"fork",[171,1457,355],{"class":354},[171,1459,1416],{"class":191},[171,1461,1462,1465,1467,1469,1472,1474],{"class":173,"line":327},[171,1463,1464],{"class":239},"            max_memory_restart",[171,1466,1390],{"class":191},[171,1468,1408],{"class":354},[171,1470,1471],{"class":358},"500M",[171,1473,355],{"class":354},[171,1475,1416],{"class":191},[171,1477,1478],{"class":173,"line":1332},[171,1479,1480],{"class":286},"            \u002F\u002F 自定义健康检查脚本\n",[171,1482,1483,1486,1488,1490,1493,1495],{"class":173,"line":1337},[171,1484,1485],{"class":239},"            health_check",[171,1487,1390],{"class":191},[171,1489,1408],{"class":354},[171,1491,1492],{"class":358},"\u002Fhealth",[171,1494,355],{"class":354},[171,1496,1416],{"class":191},[171,1498,1499],{"class":173,"line":1343},[171,1500,1501],{"class":286},"            \u002F\u002F 重启策略\n",[171,1503,1504,1507,1509,1511,1514,1516],{"class":173,"line":1351},[171,1505,1506],{"class":239},"            min_uptime",[171,1508,1390],{"class":191},[171,1510,1408],{"class":354},[171,1512,1513],{"class":358},"10s",[171,1515,355],{"class":354},[171,1517,1416],{"class":191},[171,1519,1521,1524,1526,1529],{"class":173,"line":1520},13,[171,1522,1523],{"class":239},"            max_restarts",[171,1525,1390],{"class":191},[171,1527,1528],{"class":366}," 10",[171,1530,1416],{"class":191},[171,1532,1534],{"class":173,"line":1533},14,[171,1535,1536],{"class":191},"        },\n",[171,1538,1540,1543],{"class":173,"line":1539},15,[171,1541,1542],{"class":242},"    ]",[171,1544,1416],{"class":191},[171,1546,1548],{"class":173,"line":1547},16,[171,1549,1550],{"class":191},"};\n",[377,1552,1554],{"id":1553},"_2-systemdlinux-系统服务","2. systemd（Linux 系统服务）",[28,1556,1557,1558,1561],{},"创建 ",[39,1559,1560],{},"\u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyapp.service","：",[162,1563,1567],{"className":1564,"code":1565,"language":1566,"meta":167,"style":167},"language-ini shiki shiki-themes material-theme-lighter github-light github-dark","[Unit]\nDescription=My Node.js App\nAfter=network.target\n\n[Service]\nType=simple\nUser=node\nWorkingDirectory=\u002Fhome\u002Fnode\u002Fapp\nExecStart=\u002Fusr\u002Fbin\u002Fnode app.js\nRestart=on-failure\nRestartSec=10s\nEnvironment=NODE_ENV=production\n\n[Install]\nWantedBy=multi-user.target\n","ini",[39,1568,1569,1574,1579,1584,1588,1593,1598,1603,1608,1613,1618,1623,1628,1632,1637],{"__ignoreMap":167},[171,1570,1571],{"class":173,"line":174},[171,1572,1573],{},"[Unit]\n",[171,1575,1576],{"class":173,"line":195},[171,1577,1578],{},"Description=My Node.js App\n",[171,1580,1581],{"class":173,"line":232},[171,1582,1583],{},"After=network.target\n",[171,1585,1586],{"class":173,"line":250},[171,1587,1215],{"emptyLinePlaceholder":1214},[171,1589,1590],{"class":173,"line":269},[171,1591,1592],{},"[Service]\n",[171,1594,1595],{"class":173,"line":290},[171,1596,1597],{},"Type=simple\n",[171,1599,1600],{"class":173,"line":321},[171,1601,1602],{},"User=node\n",[171,1604,1605],{"class":173,"line":327},[171,1606,1607],{},"WorkingDirectory=\u002Fhome\u002Fnode\u002Fapp\n",[171,1609,1610],{"class":173,"line":1332},[171,1611,1612],{},"ExecStart=\u002Fusr\u002Fbin\u002Fnode app.js\n",[171,1614,1615],{"class":173,"line":1337},[171,1616,1617],{},"Restart=on-failure\n",[171,1619,1620],{"class":173,"line":1343},[171,1621,1622],{},"RestartSec=10s\n",[171,1624,1625],{"class":173,"line":1351},[171,1626,1627],{},"Environment=NODE_ENV=production\n",[171,1629,1630],{"class":173,"line":1520},[171,1631,1215],{"emptyLinePlaceholder":1214},[171,1633,1634],{"class":173,"line":1533},[171,1635,1636],{},"[Install]\n",[171,1638,1639],{"class":173,"line":1539},[171,1640,1641],{},"WantedBy=multi-user.target\n",[28,1643,1644],{},"启用并启动：",[162,1646,1648],{"className":1256,"code":1647,"language":1258,"meta":167,"style":167},"systemctl enable myapp\nsystemctl start myapp\n",[39,1649,1650,1661],{"__ignoreMap":167},[171,1651,1652,1655,1658],{"class":173,"line":174},[171,1653,1654],{"class":181},"systemctl",[171,1656,1657],{"class":358}," enable",[171,1659,1660],{"class":358}," myapp\n",[171,1662,1663,1665,1667],{"class":173,"line":195},[171,1664,1654],{"class":181},[171,1666,1273],{"class":358},[171,1668,1660],{"class":358},[377,1670,1672],{"id":1671},"_3-健康检查-api-实现","3. 健康检查 API 实现",[28,1674,1675,1676,1678],{},"应用本身应提供一个 HTTP 端点（如 ",[39,1677,1492],{},"），返回 200 表示正常。",[162,1680,1682],{"className":164,"code":1681,"language":166,"meta":167,"style":167},"app.get(\"\u002Fhealth\", (req, res) => {\n    \u002F\u002F 检查数据库、缓存等关键依赖状态\n    const isHealthy = checkDependencies();\n    res.status(isHealthy ? 200 : 503).json({ status: isHealthy ? \"up\" : \"down\" });\n});\n",[39,1683,1684,1719,1724,1741,1812],{"__ignoreMap":167},[171,1685,1686,1688,1690,1693,1695,1697,1699,1701,1703,1705,1708,1710,1713,1715,1717],{"class":173,"line":174},[171,1687,1411],{"class":242},[171,1689,257],{"class":191},[171,1691,1692],{"class":298},"get",[171,1694,201],{"class":242},[171,1696,355],{"class":354},[171,1698,1492],{"class":358},[171,1700,355],{"class":354},[171,1702,208],{"class":191},[171,1704,653],{"class":191},[171,1706,1707],{"class":204},"req",[171,1709,208],{"class":191},[171,1711,1712],{"class":204}," res",[171,1714,227],{"class":191},[171,1716,519],{"class":177},[171,1718,192],{"class":191},[171,1720,1721],{"class":173,"line":195},[171,1722,1723],{"class":286},"    \u002F\u002F 检查数据库、缓存等关键依赖状态\n",[171,1725,1726,1729,1732,1734,1737,1739],{"class":173,"line":232},[171,1727,1728],{"class":177},"    const",[171,1730,1731],{"class":235}," isHealthy",[171,1733,220],{"class":219},[171,1735,1736],{"class":298}," checkDependencies",[171,1738,595],{"class":239},[171,1740,247],{"class":191},[171,1742,1743,1746,1748,1751,1753,1756,1759,1762,1765,1768,1770,1772,1775,1777,1780,1783,1785,1787,1789,1791,1794,1796,1798,1800,1803,1805,1808,1810],{"class":173,"line":250},[171,1744,1745],{"class":242},"    res",[171,1747,257],{"class":191},[171,1749,1750],{"class":298},"status",[171,1752,201],{"class":239},[171,1754,1755],{"class":242},"isHealthy",[171,1757,1758],{"class":219}," ?",[171,1760,1761],{"class":366}," 200",[171,1763,1764],{"class":219}," :",[171,1766,1767],{"class":366}," 503",[171,1769,227],{"class":239},[171,1771,257],{"class":191},[171,1773,1774],{"class":298},"json",[171,1776,201],{"class":239},[171,1778,1779],{"class":191},"{",[171,1781,1782],{"class":239}," status",[171,1784,1390],{"class":191},[171,1786,1731],{"class":242},[171,1788,1758],{"class":219},[171,1790,1408],{"class":354},[171,1792,1793],{"class":358},"up",[171,1795,355],{"class":354},[171,1797,1764],{"class":219},[171,1799,1408],{"class":354},[171,1801,1802],{"class":358},"down",[171,1804,355],{"class":354},[171,1806,1807],{"class":191}," }",[171,1809,227],{"class":239},[171,1811,247],{"class":191},[171,1813,1814,1816,1818],{"class":173,"line":269},[171,1815,424],{"class":191},[171,1817,227],{"class":242},[171,1819,247],{"class":191},[28,1821,1822],{},"Kubernetes 等编排系统可基于此端点进行存活探针（livenessProbe）和就绪探针（readinessProbe）。",[31,1824,1826],{"id":1825},"六最佳实践总结","六、最佳实践总结",[1828,1829,1830,1844,1856,1867,1873,1879],"ul",{},[1831,1832,1833,570,1836,1838,1839,1841,1842,42],"li",{},[157,1834,1835],{},"始终捕获异步错误",[39,1837,569],{}," + ",[39,1840,383],{},"，或 Promise ",[39,1843,820],{},[1831,1845,1846,1849,1850,1852,1853,1855],{},[157,1847,1848],{},"定义业务错误类","：继承 ",[39,1851,41],{}," 并添加状态码、",[39,1854,276],{}," 标志，与非操作错误（程序缺陷）区分。",[1831,1857,1858,1561,1861,1863,1864,1866],{},[157,1859,1860],{},"注册全局处理器",[39,1862,851],{}," 和 ",[39,1865,971],{}," 用于记录日志并优雅退出，而非维持运行。",[1831,1868,1869,1872],{},[157,1870,1871],{},"合理设置退出码","：表示失败原因，便于进程管理器判断是否需要重启。",[1831,1874,1875,1878],{},[157,1876,1877],{},"使用进程管理器","：PM2 或 systemd 实现自动重启、日志管理和资源限制。",[1831,1880,1881,1884,1885,817,1887,1890],{},[157,1882,1883],{},"实现健康检查端点","：暴露 ",[39,1886,1492],{},[39,1888,1889],{},"\u002Fready","，让外部系统了解服务状态。",[28,1892,1893],{},"通过以上措施，可以构建高可靠性的 Node.js 应用，有效应对各类运行时错误。",[1895,1896,1897],"style",{},"html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":167,"searchDepth":195,"depth":195,"links":1899},[1900],{"id":25,"depth":195,"text":26,"children":1901},[1902,1903,1904,1905,1906,1907],{"id":33,"depth":232,"text":34},{"id":374,"depth":232,"text":375},{"id":804,"depth":232,"text":805},{"id":1063,"depth":232,"text":1064},{"id":1245,"depth":232,"text":1246},{"id":1825,"depth":232,"text":1826},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FNodeJs\u002Ferror","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FNodeJs\u002Ferror.md","md",{"items":1913},[1914,1918,1922,1926,1930,1934],{"path":1915,"title":1916,"description":1917,"category":10,"score":290},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Ffs","文件系统","Node.js 的 fs 模块提供了与文件系统交互的 API，几乎涵盖了所有标准文件操作。它支持三种风格的 API：同步、回调式异步 和 Promise 式异步。下面详细介绍这些 API 的选择策略、流式读写、文件监视以及常用操作。",{"path":1919,"title":1920,"description":1921,"category":10,"score":290},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fasync","异步编程与模式","Node.js 的核心优势在于异步非阻塞 I\u002FO，但这也带来了回调地狱、错误处理复杂等问题。下面从解救方案、工具函数、并发控制、异步迭代以及常见反模式等角度展开。",{"path":1923,"title":1924,"description":1925,"category":10,"score":290},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fbuffer","缓冲区","Buffer 是 Node.js 全局对象，用于处理二进制数据流（如文件、网络数据）。在 ES6 引入 TypedArray 之前，Buffer 是 Node.js 处理二进制的主要方式；现在 Buffer 实现了 Uint8Arra…",{"path":1927,"title":1928,"description":1929,"category":10,"score":290},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fvar","全局对象与变量","Node.js 提供模块内可直接使用的全局对象；与浏览器 window 不同，模块顶层的 const\u002Flet 不会挂到 global。见 后端入门概览、模块系统。",{"path":1931,"title":1932,"description":1933,"category":10,"score":290},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent-loop","事件循环","Node.js 的事件循环是其实现非阻塞 I\u002FO 的核心机制。它基于 libuv 库，将各种异步操作（定时器、I\u002FO、setImmediate 等）组织成不同的阶段，每个阶段都有一个先进先出的回调队列。事件循环会按照固定的顺序反复执行…",{"path":1935,"title":1936,"description":1937,"category":10,"score":290},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fpath","路径处理","path 模块提供了用于处理和转换文件路径的实用工具。它是 Node.js 核心模块，无需安装即可直接使用。由于不同操作系统（Windows、Linux、macOS）的路径分隔符不同（Windows 使用反斜杠 \\，POSIX 使用正…",{"series":1939,"title":12,"items":1940,"index":195,"prev":1978,"next":1979},"booklet\u002Fend\u002Fnodejs",[1941,1943,1945,1946,1950,1952,1954,1958,1962,1966,1968,1972,1976],{"path":1919,"title":1920,"date":1942,"pinned":15},"2025-08-20",{"path":1923,"title":1924,"date":1944,"pinned":15},"2025-01-30",{"path":7,"title":8,"date":14,"pinned":15},{"path":1947,"title":1948,"date":1949,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent","事件驱动与非阻塞 I\u002FO 模型","2020-06-20",{"path":1931,"title":1932,"date":1951,"pinned":15},"2024-11-20",{"path":1915,"title":1916,"date":1953,"pinned":15},"2026-06-04",{"path":1955,"title":1956,"date":1957,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fhttp","网络编程","2023-01-27",{"path":1959,"title":1960,"date":1961,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fmodule","模块系统","2020-07-01",{"path":1963,"title":1964,"date":1965,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fother","其他常用模块","2020-03-27",{"path":1935,"title":1936,"date":1967,"pinned":15},"2024-03-14",{"path":1969,"title":1970,"date":1971,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fprocess","进程与子进程","2023-11-10",{"path":1973,"title":1974,"date":1975,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fstream","流","2022-05-03",{"path":1927,"title":1928,"date":1977,"pinned":15},"2025-01-03",{"path":1923,"title":1924,"date":1944,"pinned":15},{"path":1947,"title":1948,"date":1949,"pinned":15}]