[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent-loop":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent-loop":1185,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent-loop":1211},{"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":1181,"stem":1182,"id":1183,"extension":1184},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent-loop","事件循环","Node.js 的事件循环是其实现非阻塞 I\u002FO 的核心机制。它基于 libuv 库，将各种异步操作（定时器、I\u002FO、setImmediate 等）组织成不同的阶段，每个阶段都有一个先进先出的回调队列。事件循环会按照固定的顺序反复执行…","技能小册",[12,13],"nodejs","event-loop","2024-11-20",false,{"type":17,"value":18,"toc":1170},"minimark",[19,22,27,41,46,49,196,199,204,218,222,227,231,236,240,281,285,295,299,307,318,323,355,360,374,377,465,475,620,629,652,656,660,687,691,714,717,720,743,749,752,964,978,981,998,1002,1115,1118,1163,1166],[20,21,8],"h1",{"id":8},[23,24,26],"h2",{"id":25},"nodejs-事件循环详解","Node.js 事件循环详解",[28,29,30,31,35,36,40],"p",{},"Node.js 的事件循环是其实现非阻塞 I\u002FO 的核心机制。它基于 ",[32,33,34],"strong",{},"libuv"," 库，将各种异步操作（定时器、I\u002FO、",[37,38,39],"code",{},"setImmediate"," 等）组织成不同的阶段，每个阶段都有一个先进先出的回调队列。事件循环会按照固定的顺序反复执行这些阶段。",[42,43,45],"h3",{"id":44},"一事件循环各阶段","一、事件循环各阶段",[28,47,48],{},"事件循环的完整阶段顺序如下（按执行顺序排列）：",[50,51,52,68],"table",{},[53,54,55],"thead",{},[56,57,58,62,65],"tr",{},[59,60,61],"th",{},"阶段",[59,63,64],{},"描述",[59,66,67],{},"主要回调",[69,70,71,99,112,125,157,174],"tbody",{},[56,72,73,79,90],{},[74,75,76],"td",{},[32,77,78],{},"timers",[74,80,81,82,85,86,89],{},"执行到期的 ",[37,83,84],{},"setTimeout"," 和 ",[37,87,88],{},"setInterval"," 回调。",[74,91,92,95,96],{},[37,93,94],{},"setTimeout(cb, delay)","、",[37,97,98],{},"setInterval(cb, delay)",[56,100,101,106,109],{},[74,102,103],{},[32,104,105],{},"pending callbacks",[74,107,108],{},"执行延迟到下一个循环迭代的 I\u002FO 回调（例如某些系统错误如 ECONNREFUSED）。",[74,110,111],{},"上一轮循环中未执行的 I\u002FO 回调",[56,113,114,119,122],{},[74,115,116],{},[32,117,118],{},"idle, prepare",[74,120,121],{},"仅内部使用，用于 libuv 内部操作。开发者无需关注。",[74,123,124],{},"-",[56,126,127,132,147],{},[74,128,129],{},[32,130,131],{},"poll",[74,133,134,137,138,95,140,95,143,146],{},[32,135,136],{},"最重要的阶段","。检索新的 I\u002FO 事件（如文件读取、网络请求完成），执行与 I\u002FO 相关的回调（除 ",[37,139,78],{},[37,141,142],{},"check",[37,144,145],{},"close"," 以外的回调）。如果没有其他异步任务，事件循环会阻塞在此阶段等待新事件。",[74,148,149,150,95,153,156],{},"I\u002FO 回调（如 ",[37,151,152],{},"fs.readFile",[37,154,155],{},"http.request"," 的回调）",[56,158,159,163,169],{},[74,160,161],{},[32,162,142],{},[74,164,165,166,168],{},"执行 ",[37,167,39],{}," 的回调。",[74,170,171],{},[37,172,173],{},"setImmediate(cb)",[56,175,176,181,188],{},[74,177,178],{},[32,179,180],{},"close callbacks",[74,182,183,184,187],{},"执行关闭回调，如 ",[37,185,186],{},"socket.on('close')","。",[74,189,190,95,192,195],{},[37,191,186],{},[37,193,194],{},"process.on('exit')"," 等",[42,197,198],{"id":198},"各阶段详细说明",[200,201,203],"h4",{"id":202},"_1-timers-阶段","1. timers 阶段",[205,206,207,215],"ul",{},[208,209,210,211,85,213,89],"li",{},"执行所有到期的 ",[37,212,84],{},[37,214,88],{},[208,216,217],{},"注意：实际执行延迟可能大于设定的阈值，因为事件循环可能被其他回调阻塞。",[200,219,221],{"id":220},"_2-pending-callbacks-阶段","2. pending callbacks 阶段",[205,223,224],{},[208,225,226],{},"执行一些上一轮循环中未处理的 I\u002FO 回调，通常是与网络或文件系统有关的错误回调（如 ECONNREFUSED）。",[200,228,230],{"id":229},"_3-idle-prepare-阶段","3. idle \u002F prepare 阶段",[205,232,233],{},[208,234,235],{},"仅 libuv 内部使用，开发者编写的 JavaScript 代码不会在此阶段执行。",[200,237,239],{"id":238},"_4-poll-阶段","4. poll 阶段",[205,241,242,278],{},[208,243,244,247,248],{},[32,245,246],{},"核心行为","：\n",[205,249,250,257],{},[208,251,252,253,256],{},"如果 poll 队列不为空，则",[32,254,255],{},"同步","取出队列中的回调依次执行，直到队列清空或达到系统上限。",[208,258,259,260],{},"如果 poll 队列为空：\n",[205,261,262,268,271],{},[208,263,264,265,267],{},"若有待执行的 ",[37,266,39],{}," 回调，则立即结束 poll 阶段，进入 check 阶段。",[208,269,270],{},"若有即将到期的 timers，则检查定时器并跳回 timers 阶段执行到期回调。",[208,272,273,274,277],{},"否则，事件循环会在此阶段",[32,275,276],{},"阻塞等待","新的 I\u002FO 事件或定时器到期，以提高效率。",[208,279,280],{},"这是 Node.js 实现高并发 I\u002FO 的关键：绝大部分时间事件循环停留在 poll 阶段，等待新的事件。",[200,282,284],{"id":283},"_5-check-阶段","5. check 阶段",[205,286,287],{},[208,288,289,290,89,292,294],{},"执行所有 ",[37,291,39],{},[37,293,39],{}," 的回调会在 I\u002FO 处理完毕后立即执行，不经过 poll 阶段的等待。",[200,296,298],{"id":297},"_6-close-callbacks-阶段","6. close callbacks 阶段",[205,300,301],{},[208,302,303,304,187],{},"执行关闭事件回调，如 ",[37,305,306],{},"socket.on('close', () => {...})",[42,308,310,311,314,315,317],{"id":309},"二processnexttick-与-setimmediate-的区别与执行时机","二、",[37,312,313],{},"process.nextTick"," 与 ",[37,316,39],{}," 的区别与执行时机",[200,319,321],{"id":320},"processnexttick",[37,322,313],{},[205,324,325,335,345],{},[208,326,327,330,331,334],{},[32,328,329],{},"不属于事件循环任何一个阶段","，而是一个独立的队列，在每个阶段",[32,332,333],{},"结束后","立即执行。",[208,336,337,338,341,342,344],{},"执行时机：当前阶段的所有回调执行完毕后，在进入下一个阶段之前，会",[32,339,340],{},"完全清空"," ",[37,343,313],{}," 队列。",[208,346,347,348,351,352,354],{},"因为 ",[37,349,350],{},"nextTick"," 会在当前阶段末尾执行，所以可被看作比任何后续阶段的回调（包括 ",[37,353,39],{},"）具有更高的优先级。",[200,356,358],{"id":357},"setimmediate",[37,359,39],{},[205,361,362,369],{},[208,363,364,365,368],{},"属于 ",[32,366,367],{},"check 阶段","的回调，会在 poll 阶段之后执行。",[208,370,371,372,344],{},"执行时机：事件循环进入 check 阶段时，清空 ",[37,373,39],{},[200,375,376],{"id":376},"区别总结",[50,378,379,394],{},[53,380,381],{},[56,382,383,386,390],{},[59,384,385],{},"特性",[59,387,388],{},[37,389,313],{},[59,391,392],{},[37,393,39],{},[69,395,396,408,421,434,452],{},[56,397,398,403,406],{},[74,399,400],{},[32,401,402],{},"所属阶段",[74,404,405],{},"独立队列，不属于事件循环任何阶段",[74,407,367],{},[56,409,410,415,418],{},[74,411,412],{},[32,413,414],{},"执行时机",[74,416,417],{},"当前阶段结束后，立即执行",[74,419,420],{},"事件循环进入 check 阶段时执行",[56,422,423,428,431],{},[74,424,425],{},[32,426,427],{},"优先级",[74,429,430],{},"非常高（立即执行）",[74,432,433],{},"较低（需经过 poll 阶段）",[56,435,436,441,447],{},[74,437,438],{},[32,439,440],{},"递归调用影响",[74,442,443,444,446],{},"递归调用 ",[37,445,350],{}," 会阻塞事件循环（导致 I\u002FO 饥饿）",[74,448,443,449,451],{},[37,450,39],{}," 不会阻塞，因为每次都会经过 poll 阶段",[56,453,454,459,462],{},[74,455,456],{},[32,457,458],{},"典型应用",[74,460,461],{},"在同一个阶段内推迟执行，或强制执行某些清理操作",[74,463,464],{},"在 I\u002FO 完成后安排工作，或实现递归异步调用",[200,466,468,469,471,472,474],{"id":467},"代码示例nexttick-vs-setimmediate-的执行顺序","代码示例：",[37,470,350],{}," vs ",[37,473,39],{}," 的执行顺序",[476,477,482],"pre",{"className":478,"code":479,"language":480,"meta":481,"style":481},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","setImmediate(() => console.log(\"setImmediate\"));\nprocess.nextTick(() => console.log(\"nextTick\"));\nconsole.log(\"同步代码\");\n\n\u002F\u002F 输出顺序：\n\u002F\u002F 同步代码\n\u002F\u002F nextTick\n\u002F\u002F setImmediate\n","js","",[37,483,484,530,564,588,595,602,608,614],{"__ignoreMap":481},[485,486,489,492,496,500,504,507,510,513,515,519,522,524,527],"span",{"class":487,"line":488},"line",1,[485,490,39],{"class":491},"sGLFI",[485,493,495],{"class":494},"su5hD","(",[485,497,499],{"class":498},"sP7_E","()",[485,501,503],{"class":502},"sbsja"," =>",[485,505,506],{"class":494}," console",[485,508,509],{"class":498},".",[485,511,512],{"class":491},"log",[485,514,495],{"class":494},[485,516,518],{"class":517},"sjJ54","\"",[485,520,39],{"class":521},"s_sjI",[485,523,518],{"class":517},[485,525,526],{"class":494},"))",[485,528,529],{"class":498},";\n",[485,531,533,536,538,540,542,544,546,548,550,552,554,556,558,560,562],{"class":487,"line":532},2,[485,534,535],{"class":494},"process",[485,537,509],{"class":498},[485,539,350],{"class":491},[485,541,495],{"class":494},[485,543,499],{"class":498},[485,545,503],{"class":502},[485,547,506],{"class":494},[485,549,509],{"class":498},[485,551,512],{"class":491},[485,553,495],{"class":494},[485,555,518],{"class":517},[485,557,350],{"class":521},[485,559,518],{"class":517},[485,561,526],{"class":494},[485,563,529],{"class":498},[485,565,567,570,572,574,576,578,581,583,586],{"class":487,"line":566},3,[485,568,569],{"class":494},"console",[485,571,509],{"class":498},[485,573,512],{"class":491},[485,575,495],{"class":494},[485,577,518],{"class":517},[485,579,580],{"class":521},"同步代码",[485,582,518],{"class":517},[485,584,585],{"class":494},")",[485,587,529],{"class":498},[485,589,591],{"class":487,"line":590},4,[485,592,594],{"emptyLinePlaceholder":593},true,"\n",[485,596,598],{"class":487,"line":597},5,[485,599,601],{"class":600},"sutJx","\u002F\u002F 输出顺序：\n",[485,603,605],{"class":487,"line":604},6,[485,606,607],{"class":600},"\u002F\u002F 同步代码\n",[485,609,611],{"class":487,"line":610},7,[485,612,613],{"class":600},"\u002F\u002F nextTick\n",[485,615,617],{"class":487,"line":616},8,[485,618,619],{"class":600},"\u002F\u002F setImmediate\n",[200,621,623,314,626,628],{"id":622},"settimeoutfn-0-与-setimmediate-的比较",[37,624,625],{},"setTimeout(fn, 0)",[37,627,39],{}," 的比较",[205,630,631,641],{},[208,632,633,634,636,637,640],{},"如果调用时机在 I\u002FO 循环内（比如在文件读取回调中），",[37,635,39],{}," 总是先于 ",[37,638,639],{},"setTimeout(fn,0)"," 执行。",[208,642,643,644,646,647,649,650,187],{},"如果在主模块中直接调用，顺序取决于事件循环启动时的性能（通常 ",[37,645,639],{}," 可能先执行，但不确定）。因此要依赖顺序时需使用 ",[37,648,39],{}," 或 ",[37,651,350],{},[42,653,655],{"id":654},"三微任务与宏任务在-node-中的表现","三、微任务与宏任务在 Node 中的表现",[200,657,659],{"id":658},"宏任务macrotask","宏任务（MacroTask）",[205,661,662],{},[208,663,664,665],{},"在 Node.js 中，宏任务可以理解为事件循环各阶段队列中的回调。\n",[205,666,667,674,677,682],{},[208,668,669,95,671,673],{},[37,670,84],{},[37,672,88],{}," → timers 阶段",[208,675,676],{},"I\u002FO 回调 → poll 阶段",[208,678,679,681],{},[37,680,39],{}," → check 阶段",[208,683,684,686],{},[37,685,145],{}," 事件 → close callbacks 阶段",[200,688,690],{"id":689},"微任务microtask","微任务（MicroTask）",[205,692,693],{},[208,694,695,696],{},"微任务包括：\n",[205,697,698,704,709],{},[208,699,700,703],{},[37,701,702],{},"Promise.then\u002Fcatch\u002Ffinally"," 回调",[208,705,706],{},[37,707,708],{},"queueMicrotask",[208,710,711,713],{},[37,712,313],{},"（严格说它更特别，优先级高于微任务）",[200,715,716],{"id":716},"执行顺序规则",[28,718,719],{},"在 Node.js 中（以官方文档和常见实现为准），执行顺序为：",[721,722,723,726,734,740],"ol",{},[208,724,725],{},"执行当前阶段的所有宏任务（如 timers 队列中的全部回调）。",[208,727,728,187],{},[32,729,730,731,733],{},"清空 ",[37,732,313],{}," 队列",[208,735,736,739],{},[32,737,738],{},"清空微任务队列","（Promise、queueMicrotask）。",[208,741,742],{},"进入事件循环的下一个阶段。",[28,744,745,746],{},"即：",[32,747,748],{},"nextTick > 微任务 (Promise) > 其他宏任务（下一阶段）",[200,750,751],{"id":751},"验证示例",[476,753,755],{"className":478,"code":754,"language":480,"meta":481,"style":481},"Promise.resolve().then(() => console.log(\"promise1\"));\nprocess.nextTick(() => console.log(\"nextTick1\"));\nsetTimeout(() => console.log(\"timeout\"), 0);\nsetImmediate(() => console.log(\"immediate\"));\n\nconsole.log(\"sync\");\n\n\u002F\u002F 输出顺序（Node 环境）：\n\u002F\u002F sync\n\u002F\u002F nextTick1\n\u002F\u002F promise1\n\u002F\u002F timeout   （或 immediate，取决于启动时机）\n\u002F\u002F immediate （或 timeout）\n",[37,756,757,800,833,871,900,904,925,929,934,940,946,952,958],{"__ignoreMap":481},[485,758,759,763,765,768,770,772,775,777,779,781,783,785,787,789,791,794,796,798],{"class":487,"line":488},[485,760,762],{"class":761},"sZMiF","Promise",[485,764,509],{"class":498},[485,766,767],{"class":491},"resolve",[485,769,499],{"class":494},[485,771,509],{"class":498},[485,773,774],{"class":491},"then",[485,776,495],{"class":494},[485,778,499],{"class":498},[485,780,503],{"class":502},[485,782,506],{"class":494},[485,784,509],{"class":498},[485,786,512],{"class":491},[485,788,495],{"class":494},[485,790,518],{"class":517},[485,792,793],{"class":521},"promise1",[485,795,518],{"class":517},[485,797,526],{"class":494},[485,799,529],{"class":498},[485,801,802,804,806,808,810,812,814,816,818,820,822,824,827,829,831],{"class":487,"line":532},[485,803,535],{"class":494},[485,805,509],{"class":498},[485,807,350],{"class":491},[485,809,495],{"class":494},[485,811,499],{"class":498},[485,813,503],{"class":502},[485,815,506],{"class":494},[485,817,509],{"class":498},[485,819,512],{"class":491},[485,821,495],{"class":494},[485,823,518],{"class":517},[485,825,826],{"class":521},"nextTick1",[485,828,518],{"class":517},[485,830,526],{"class":494},[485,832,529],{"class":498},[485,834,835,837,839,841,843,845,847,849,851,853,856,858,860,863,867,869],{"class":487,"line":566},[485,836,84],{"class":491},[485,838,495],{"class":494},[485,840,499],{"class":498},[485,842,503],{"class":502},[485,844,506],{"class":494},[485,846,509],{"class":498},[485,848,512],{"class":491},[485,850,495],{"class":494},[485,852,518],{"class":517},[485,854,855],{"class":521},"timeout",[485,857,518],{"class":517},[485,859,585],{"class":494},[485,861,862],{"class":498},",",[485,864,866],{"class":865},"srdBf"," 0",[485,868,585],{"class":494},[485,870,529],{"class":498},[485,872,873,875,877,879,881,883,885,887,889,891,894,896,898],{"class":487,"line":590},[485,874,39],{"class":491},[485,876,495],{"class":494},[485,878,499],{"class":498},[485,880,503],{"class":502},[485,882,506],{"class":494},[485,884,509],{"class":498},[485,886,512],{"class":491},[485,888,495],{"class":494},[485,890,518],{"class":517},[485,892,893],{"class":521},"immediate",[485,895,518],{"class":517},[485,897,526],{"class":494},[485,899,529],{"class":498},[485,901,902],{"class":487,"line":597},[485,903,594],{"emptyLinePlaceholder":593},[485,905,906,908,910,912,914,916,919,921,923],{"class":487,"line":604},[485,907,569],{"class":494},[485,909,509],{"class":498},[485,911,512],{"class":491},[485,913,495],{"class":494},[485,915,518],{"class":517},[485,917,918],{"class":521},"sync",[485,920,518],{"class":517},[485,922,585],{"class":494},[485,924,529],{"class":498},[485,926,927],{"class":487,"line":610},[485,928,594],{"emptyLinePlaceholder":593},[485,930,931],{"class":487,"line":616},[485,932,933],{"class":600},"\u002F\u002F 输出顺序（Node 环境）：\n",[485,935,937],{"class":487,"line":936},9,[485,938,939],{"class":600},"\u002F\u002F sync\n",[485,941,943],{"class":487,"line":942},10,[485,944,945],{"class":600},"\u002F\u002F nextTick1\n",[485,947,949],{"class":487,"line":948},11,[485,950,951],{"class":600},"\u002F\u002F promise1\n",[485,953,955],{"class":487,"line":954},12,[485,956,957],{"class":600},"\u002F\u002F timeout   （或 immediate，取决于启动时机）\n",[485,959,961],{"class":487,"line":960},13,[485,962,963],{"class":600},"\u002F\u002F immediate （或 timeout）\n",[28,965,966,967,85,969,971,972,85,974,977],{},"注意：",[37,968,855],{},[37,970,893],{}," 的顺序在非 I\u002FO 循环中不固定；但 ",[37,973,350],{},[37,975,976],{},"promise"," 的先后是确定的。",[200,979,980],{"id":980},"特殊说明",[205,982,983,988],{},[208,984,985,987],{},[37,986,313],{}," 的优先级高于标准微任务，这是 Node.js 的设计选择，目的是让开发者能够在当前操作完成后立即执行某些任务，而不必等到微任务队列清空。",[208,989,990,991,993,994,649,996,187],{},"滥用 ",[37,992,313],{}," 会导致事件循环无法进入 poll 阶段，造成 I\u002FO 饥饿。官方建议优先使用 ",[37,995,39],{},[37,997,762],{},[42,999,1001],{"id":1000},"四总结表格","四、总结表格",[50,1003,1004,1019],{},[53,1005,1006],{},[56,1007,1008,1011,1014,1017],{},[59,1009,1010],{},"类型",[59,1012,1013],{},"代表 API",[59,1015,1016],{},"执行阶段\u002F时机",[59,1018,427],{},[69,1020,1021,1038,1052,1067,1082,1100],{},[56,1022,1023,1026,1032,1035],{},[74,1024,1025],{},"宏任务（timers）",[74,1027,1028,95,1030],{},[37,1029,84],{},[37,1031,88],{},[74,1033,1034],{},"timers 阶段（每轮最先）",[74,1036,1037],{},"低（受延迟和队列影响）",[56,1039,1040,1043,1046,1049],{},[74,1041,1042],{},"宏任务（poll）",[74,1044,1045],{},"文件 I\u002FO、网络 I\u002FO 回调",[74,1047,1048],{},"poll 阶段",[74,1050,1051],{},"中",[56,1053,1054,1057,1061,1064],{},[74,1055,1056],{},"宏任务（check）",[74,1058,1059],{},[37,1060,39],{},[74,1062,1063],{},"check 阶段（poll 之后）",[74,1065,1066],{},"中低",[56,1068,1069,1072,1076,1079],{},[74,1070,1071],{},"宏任务（close）",[74,1073,1074],{},[37,1075,186],{},[74,1077,1078],{},"close callbacks 阶段（最后）",[74,1080,1081],{},"最低",[56,1083,1084,1087,1094,1097],{},[74,1085,1086],{},"微任务",[74,1088,1089,95,1092],{},[37,1090,1091],{},"Promise.then",[37,1093,708],{},[74,1095,1096],{},"当前阶段结束后、nextTick 之后",[74,1098,1099],{},"高",[56,1101,1102,1105,1109,1112],{},[74,1103,1104],{},"特殊队列",[74,1106,1107],{},[37,1108,313],{},[74,1110,1111],{},"当前阶段结束后、微任务之前",[74,1113,1114],{},"最高",[23,1116,1117],{"id":1117},"推荐参考资料",[721,1119,1120,1136,1146,1152],{},[208,1121,1122,1125,1126],{},[32,1123,1124],{},"Node.js 官方文档","：",[1127,1128,1132,1133],"a",{"href":1129,"rel":1130},"https:\u002F\u002Fnodejs.org\u002Fen\u002Fdocs\u002Fguides\u002Fevent-loop-timers-and-nexttick\u002F",[1131],"nofollow","The Node.js Event Loop, Timers, and ",[37,1134,1135],{},"process.nextTick()",[208,1137,1138,1125,1141],{},[32,1139,1140],{},"libuv 文档",[1127,1142,1145],{"href":1143,"rel":1144},"http:\u002F\u002Fdocs.libuv.org\u002Fen\u002Fv1.x\u002Fdesign.html",[1131],"Design overview of libuv",[208,1147,1148,1151],{},[32,1149,1150],{},"深入理解 Node.js 事件循环","：《Node.js 设计模式》第 2 章",[208,1153,1154,1157,1158],{},[32,1155,1156],{},"高性能 Node.js 最佳实践","：官方博客文章 ",[1127,1159,1162],{"href":1160,"rel":1161},"https:\u002F\u002Fnodejs.org\u002Fen\u002Fdocs\u002Fguides\u002Fdont-block-the-event-loop\u002F",[1131],"Don't Block the Event Loop",[28,1164,1165],{},"理解事件循环是编写高性能、可预测的 Node.js 应用的基础，尤其是在处理大量 I\u002FO 或需要精细控制异步任务顺序时。",[1167,1168,1169],"style",{},"html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}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 .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 .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 .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":481,"searchDepth":532,"depth":532,"links":1171},[1172,1180],{"id":25,"depth":532,"text":26,"children":1173},[1174,1175,1176,1178,1179],{"id":44,"depth":566,"text":45},{"id":198,"depth":566,"text":198},{"id":309,"depth":566,"text":1177},"二、process.nextTick 与 setImmediate 的区别与执行时机",{"id":654,"depth":566,"text":655},{"id":1000,"depth":566,"text":1001},{"id":1117,"depth":532,"text":1117},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FNodeJs\u002Fbase\u002Fevent-loop","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FNodeJs\u002Fbase\u002Fevent-loop.md","md",{"items":1186},[1187,1191,1195,1199,1203,1207],{"path":1188,"title":1189,"description":1190,"category":10,"score":604},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fvar","全局对象与变量","Node.js 提供模块内可直接使用的全局对象；与浏览器 window 不同，模块顶层的 const\u002Flet 不会挂到 global。见 后端入门概览、模块系统。",{"path":1192,"title":1193,"description":1194,"category":10,"score":604},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fmodule","模块系统","Node.js 的模块系统是其核心设计之一，它允许开发者将代码拆分为多个文件（模块），通过 require（CommonJS）或 import\u002Fexport（ESM）进行组织和复用。下面详细介绍 CommonJS、ESM 以及两者的互操作。",{"path":1196,"title":1197,"description":1198,"category":10,"score":604},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent","事件驱动与非阻塞 I\u002FO 模型","Node.js 的底层架构核心是事件驱动与非阻塞 I\u002FO：以 V8 引擎执行 JavaScript、libuv 库处理底层 I\u002FO 与事件循环。涵盖 libuv 线程池、事件循环各阶段、EventEmitter 实践、最佳实践与常见坑。",{"path":1200,"title":1201,"description":1202,"category":10,"score":590},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fbasics","后端入门概览","本目录覆盖 JavaScript\u002FTypeScript 服务端运行时与框架、数据存储，以及 Rust 系统编程入门，提供从零到部署的完整学习路径。前置建议：JavaScript 基础、工程化 · 环境变量。",{"path":1204,"title":1205,"description":1206,"category":10,"score":590},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Ffs","文件系统","Node.js 的 fs 模块提供了与文件系统交互的 API，几乎涵盖了所有标准文件操作。它支持三种风格的 API：同步、回调式异步 和 Promise 式异步。下面详细介绍这些 API 的选择策略、流式读写、文件监视以及常用操作。",{"path":1208,"title":1209,"description":1210,"category":10,"score":590},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fasync","异步编程与模式","Node.js 的核心优势在于异步非阻塞 I\u002FO，但这也带来了回调地狱、错误处理复杂等问题。下面从解救方案、工具函数、并发控制、异步迭代以及常见反模式等角度展开。",{"series":1212,"title":1213,"items":1214,"index":488,"prev":1222,"next":1223},"booklet\u002Fend\u002Fnodejs\u002Fbase","base",[1215,1217,1218,1220],{"path":1196,"title":1197,"date":1216,"pinned":15},"2020-06-20",{"path":7,"title":8,"date":14,"pinned":15},{"path":1192,"title":1193,"date":1219,"pinned":15},"2020-07-01",{"path":1188,"title":1189,"date":1221,"pinned":15},"2025-01-03",{"path":1196,"title":1197,"date":1216,"pinned":15},{"path":1192,"title":1193,"date":1219,"pinned":15}]