[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice":2247,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice":2273},{"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":2243,"stem":2244,"id":2245,"extension":2246},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice","提供者与服务","Service 是最常见的 Provider，封装业务逻辑。见 module。","技能小册",[12,13],"nestjs","service","2024-12-02",false,{"type":17,"value":18,"toc":2232},"minimark",[19,22,37,45,50,53,61,66,408,412,418,704,708,711,855,858,862,876,883,891,894,1039,1046,1120,1127,1130,1372,1379,1385,1556,1563,1570,1573,1645,1656,1660,1670,1673,1791,1798,1808,1905,1909,1920,1924,1930,1949,1952,2046,2049,2167,2170,2174,2177,2228],[20,21,8],"h1",{"id":8},[23,24,25,26,30,31,36],"p",{},"Service 是最常见的 ",[27,28,29],"strong",{},"Provider","，封装业务逻辑。见 ",[32,33,35],"a",{"href":34},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule","module","。",[23,38,39,40,44],{},"提供者（Providers）是 NestJS 依赖注入体系的核心。服务（Service）是一种最常见的提供者，通常使用 ",[41,42,43],"code",{},"@Injectable()"," 装饰器。除了服务类，NestJS 还支持多种自定义提供者方式，满足不同场景的注入需求。",[46,47,49],"h3",{"id":48},"一服务service","一、服务（Service）",[23,51,52],{},"服务用于封装业务逻辑，如数据验证、数据库操作、调用外部 API 等。控制器负责处理请求，服务负责执行业务，保持关注点分离。",[54,55,57,58,60],"h4",{"id":56},"_1-使用-injectable-装饰器","1. 使用 ",[41,59,43],{}," 装饰器",[23,62,63,65],{},[41,64,43],{}," 标记一个类可以被 NestJS 的 IoC 容器管理，并注入到其他类中。",[67,68,73],"pre",{"className":69,"code":70,"language":71,"meta":72,"style":72},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","\u002F\u002F users.service.ts\nimport { Injectable } from \"@nestjs\u002Fcommon\";\n\n@Injectable()\nexport class UsersService {\n  private users = [{ id: 1, name: \"John\" }];\n\n  findOne(id: number) {\n    return this.users.find((user) => user.id === id);\n  }\n\n  create(user: { name: string }) {\n    const newUser = { id: Date.now(), ...user };\n    this.users.push(newUser);\n    return newUser;\n  }\n}\n","ts","",[41,74,75,84,119,126,139,156,209,214,239,288,294,299,325,364,388,397,402],{"__ignoreMap":72},[76,77,80],"span",{"class":78,"line":79},"line",1,[76,81,83],{"class":82},"sutJx","\u002F\u002F users.service.ts\n",[76,85,87,91,95,99,102,105,109,113,116],{"class":78,"line":86},2,[76,88,90],{"class":89},"sVHd0","import",[76,92,94],{"class":93},"sP7_E"," {",[76,96,98],{"class":97},"su5hD"," Injectable",[76,100,101],{"class":93}," }",[76,103,104],{"class":89}," from",[76,106,108],{"class":107},"sjJ54"," \"",[76,110,112],{"class":111},"s_sjI","@nestjs\u002Fcommon",[76,114,115],{"class":107},"\"",[76,117,118],{"class":93},";\n",[76,120,122],{"class":78,"line":121},3,[76,123,125],{"emptyLinePlaceholder":124},true,"\n",[76,127,129,132,136],{"class":78,"line":128},4,[76,130,131],{"class":93},"@",[76,133,135],{"class":134},"sGLFI","Injectable",[76,137,138],{"class":97},"()\n",[76,140,142,145,149,153],{"class":78,"line":141},5,[76,143,144],{"class":89},"export",[76,146,148],{"class":147},"sbsja"," class",[76,150,152],{"class":151},"sbgvK"," UsersService",[76,154,155],{"class":93}," {\n",[76,157,159,162,166,170,173,176,180,183,187,190,193,195,197,200,202,204,207],{"class":78,"line":158},6,[76,160,161],{"class":147},"  private",[76,163,165],{"class":164},"sucvu"," users",[76,167,169],{"class":168},"smGrS"," =",[76,171,172],{"class":97}," [",[76,174,175],{"class":93},"{",[76,177,179],{"class":178},"skxfh"," id",[76,181,182],{"class":93},":",[76,184,186],{"class":185},"srdBf"," 1",[76,188,189],{"class":93},",",[76,191,192],{"class":178}," name",[76,194,182],{"class":93},[76,196,108],{"class":107},[76,198,199],{"class":111},"John",[76,201,115],{"class":107},[76,203,101],{"class":93},[76,205,206],{"class":97},"]",[76,208,118],{"class":93},[76,210,212],{"class":78,"line":211},7,[76,213,125],{"emptyLinePlaceholder":124},[76,215,217,221,224,228,230,234,237],{"class":78,"line":216},8,[76,218,220],{"class":219},"sVXei","  findOne",[76,222,223],{"class":93},"(",[76,225,227],{"class":226},"s99_P","id",[76,229,182],{"class":168},[76,231,233],{"class":232},"sZMiF"," number",[76,235,236],{"class":93},")",[76,238,155],{"class":93},[76,240,242,245,249,252,255,257,260,262,264,267,269,272,275,277,279,282,284,286],{"class":78,"line":241},9,[76,243,244],{"class":89},"    return",[76,246,248],{"class":247},"s39Yj"," this",[76,250,251],{"class":93},".",[76,253,254],{"class":97},"users",[76,256,251],{"class":93},[76,258,259],{"class":134},"find",[76,261,223],{"class":178},[76,263,223],{"class":93},[76,265,266],{"class":226},"user",[76,268,236],{"class":93},[76,270,271],{"class":147}," =>",[76,273,274],{"class":97}," user",[76,276,251],{"class":93},[76,278,227],{"class":97},[76,280,281],{"class":168}," ===",[76,283,179],{"class":97},[76,285,236],{"class":178},[76,287,118],{"class":93},[76,289,291],{"class":78,"line":290},10,[76,292,293],{"class":93},"  }\n",[76,295,297],{"class":78,"line":296},11,[76,298,125],{"emptyLinePlaceholder":124},[76,300,302,305,307,309,311,313,315,317,320,323],{"class":78,"line":301},12,[76,303,304],{"class":219},"  create",[76,306,223],{"class":93},[76,308,266],{"class":226},[76,310,182],{"class":168},[76,312,94],{"class":93},[76,314,192],{"class":164},[76,316,182],{"class":168},[76,318,319],{"class":232}," string",[76,321,322],{"class":93}," })",[76,324,155],{"class":93},[76,326,328,331,335,337,339,341,343,346,348,351,354,356,359,361],{"class":78,"line":327},13,[76,329,330],{"class":147},"    const",[76,332,334],{"class":333},"s_hVV"," newUser",[76,336,169],{"class":168},[76,338,94],{"class":93},[76,340,179],{"class":178},[76,342,182],{"class":93},[76,344,345],{"class":97}," Date",[76,347,251],{"class":93},[76,349,350],{"class":134},"now",[76,352,353],{"class":178},"()",[76,355,189],{"class":93},[76,357,358],{"class":168}," ...",[76,360,266],{"class":97},[76,362,363],{"class":93}," };\n",[76,365,367,370,372,374,376,379,381,384,386],{"class":78,"line":366},14,[76,368,369],{"class":247},"    this",[76,371,251],{"class":93},[76,373,254],{"class":97},[76,375,251],{"class":93},[76,377,378],{"class":134},"push",[76,380,223],{"class":178},[76,382,383],{"class":97},"newUser",[76,385,236],{"class":178},[76,387,118],{"class":93},[76,389,391,393,395],{"class":78,"line":390},15,[76,392,244],{"class":89},[76,394,334],{"class":97},[76,396,118],{"class":93},[76,398,400],{"class":78,"line":399},16,[76,401,293],{"class":93},[76,403,405],{"class":78,"line":404},17,[76,406,407],{"class":93},"}\n",[54,409,411],{"id":410},"_2-在控制器中注入服务","2. 在控制器中注入服务",[23,413,414,415,36],{},"通过构造函数注入，NestJS 会自动实例化并提供 ",[41,416,417],{},"UsersService",[67,419,421],{"className":69,"code":420,"language":71,"meta":72,"style":72},"\u002F\u002F users.controller.ts\nimport { Controller, Get, Param, Post, Body } from \"@nestjs\u002Fcommon\";\nimport { UsersService } from \".\u002Fusers.service\";\n\n@Controller(\"users\")\nexport class UsersController {\n  constructor(private readonly usersService: UsersService) {}\n\n  @Get(\":id\")\n  findOne(@Param(\"id\") id: number) {\n    return this.usersService.findOne(id);\n  }\n\n  @Post()\n  create(@Body() body: { name: string }) {\n    return this.usersService.create(body);\n  }\n}\n",[41,422,423,428,469,490,494,512,523,548,552,571,602,626,630,634,643,672,695,699],{"__ignoreMap":72},[76,424,425],{"class":78,"line":79},[76,426,427],{"class":82},"\u002F\u002F users.controller.ts\n",[76,429,430,432,434,437,439,442,444,447,449,452,454,457,459,461,463,465,467],{"class":78,"line":86},[76,431,90],{"class":89},[76,433,94],{"class":93},[76,435,436],{"class":97}," Controller",[76,438,189],{"class":93},[76,440,441],{"class":97}," Get",[76,443,189],{"class":93},[76,445,446],{"class":97}," Param",[76,448,189],{"class":93},[76,450,451],{"class":97}," Post",[76,453,189],{"class":93},[76,455,456],{"class":97}," Body",[76,458,101],{"class":93},[76,460,104],{"class":89},[76,462,108],{"class":107},[76,464,112],{"class":111},[76,466,115],{"class":107},[76,468,118],{"class":93},[76,470,471,473,475,477,479,481,483,486,488],{"class":78,"line":121},[76,472,90],{"class":89},[76,474,94],{"class":93},[76,476,152],{"class":97},[76,478,101],{"class":93},[76,480,104],{"class":89},[76,482,108],{"class":107},[76,484,485],{"class":111},".\u002Fusers.service",[76,487,115],{"class":107},[76,489,118],{"class":93},[76,491,492],{"class":78,"line":128},[76,493,125],{"emptyLinePlaceholder":124},[76,495,496,498,501,503,505,507,509],{"class":78,"line":141},[76,497,131],{"class":93},[76,499,500],{"class":134},"Controller",[76,502,223],{"class":97},[76,504,115],{"class":107},[76,506,254],{"class":111},[76,508,115],{"class":107},[76,510,511],{"class":97},")\n",[76,513,514,516,518,521],{"class":78,"line":158},[76,515,144],{"class":89},[76,517,148],{"class":147},[76,519,520],{"class":151}," UsersController",[76,522,155],{"class":93},[76,524,525,528,530,533,536,539,541,543,545],{"class":78,"line":211},[76,526,527],{"class":147},"  constructor",[76,529,223],{"class":93},[76,531,532],{"class":147},"private",[76,534,535],{"class":147}," readonly",[76,537,538],{"class":226}," usersService",[76,540,182],{"class":168},[76,542,152],{"class":151},[76,544,236],{"class":93},[76,546,547],{"class":93}," {}\n",[76,549,550],{"class":78,"line":216},[76,551,125],{"emptyLinePlaceholder":124},[76,553,554,557,560,562,564,567,569],{"class":78,"line":241},[76,555,556],{"class":93},"  @",[76,558,559],{"class":134},"Get",[76,561,223],{"class":97},[76,563,115],{"class":107},[76,565,566],{"class":111},":id",[76,568,115],{"class":107},[76,570,511],{"class":97},[76,572,573,575,578,581,583,585,587,589,592,594,596,598,600],{"class":78,"line":290},[76,574,220],{"class":219},[76,576,577],{"class":93},"(@",[76,579,580],{"class":134},"Param",[76,582,223],{"class":97},[76,584,115],{"class":107},[76,586,227],{"class":111},[76,588,115],{"class":107},[76,590,591],{"class":97},") ",[76,593,227],{"class":226},[76,595,182],{"class":168},[76,597,233],{"class":232},[76,599,236],{"class":93},[76,601,155],{"class":93},[76,603,604,606,608,610,613,615,618,620,622,624],{"class":78,"line":296},[76,605,244],{"class":89},[76,607,248],{"class":247},[76,609,251],{"class":93},[76,611,612],{"class":97},"usersService",[76,614,251],{"class":93},[76,616,617],{"class":134},"findOne",[76,619,223],{"class":178},[76,621,227],{"class":97},[76,623,236],{"class":178},[76,625,118],{"class":93},[76,627,628],{"class":78,"line":301},[76,629,293],{"class":93},[76,631,632],{"class":78,"line":327},[76,633,125],{"emptyLinePlaceholder":124},[76,635,636,638,641],{"class":78,"line":366},[76,637,556],{"class":93},[76,639,640],{"class":134},"Post",[76,642,138],{"class":97},[76,644,645,647,649,652,655,658,660,662,664,666,668,670],{"class":78,"line":390},[76,646,304],{"class":219},[76,648,577],{"class":93},[76,650,651],{"class":134},"Body",[76,653,654],{"class":97},"() ",[76,656,657],{"class":226},"body",[76,659,182],{"class":168},[76,661,94],{"class":93},[76,663,192],{"class":164},[76,665,182],{"class":168},[76,667,319],{"class":232},[76,669,322],{"class":93},[76,671,155],{"class":93},[76,673,674,676,678,680,682,684,687,689,691,693],{"class":78,"line":399},[76,675,244],{"class":89},[76,677,248],{"class":247},[76,679,251],{"class":93},[76,681,612],{"class":97},[76,683,251],{"class":93},[76,685,686],{"class":134},"create",[76,688,223],{"class":178},[76,690,657],{"class":97},[76,692,236],{"class":178},[76,694,118],{"class":93},[76,696,697],{"class":78,"line":404},[76,698,293],{"class":93},[76,700,702],{"class":78,"line":701},18,[76,703,407],{"class":93},[54,705,707],{"id":706},"_3-服务之间的相互依赖","3. 服务之间的相互依赖",[23,709,710],{},"服务也可以注入其他服务，形成清晰的层级。只需在构造函数中声明即可。",[67,712,714],{"className":69,"code":713,"language":71,"meta":72,"style":72},"@Injectable()\nexport class OrderService {\n  constructor(private readonly usersService: UsersService) {}\n\n  getOrderWithUser(orderId: number) {\n    const order = this.findOrder(orderId);\n    const user = this.usersService.findOne(order.userId);\n    return { order, user };\n  }\n}\n",[41,715,716,724,735,755,759,777,801,833,847,851],{"__ignoreMap":72},[76,717,718,720,722],{"class":78,"line":79},[76,719,131],{"class":93},[76,721,135],{"class":134},[76,723,138],{"class":97},[76,725,726,728,730,733],{"class":78,"line":86},[76,727,144],{"class":89},[76,729,148],{"class":147},[76,731,732],{"class":151}," OrderService",[76,734,155],{"class":93},[76,736,737,739,741,743,745,747,749,751,753],{"class":78,"line":121},[76,738,527],{"class":147},[76,740,223],{"class":93},[76,742,532],{"class":147},[76,744,535],{"class":147},[76,746,538],{"class":226},[76,748,182],{"class":168},[76,750,152],{"class":151},[76,752,236],{"class":93},[76,754,547],{"class":93},[76,756,757],{"class":78,"line":128},[76,758,125],{"emptyLinePlaceholder":124},[76,760,761,764,766,769,771,773,775],{"class":78,"line":141},[76,762,763],{"class":219},"  getOrderWithUser",[76,765,223],{"class":93},[76,767,768],{"class":226},"orderId",[76,770,182],{"class":168},[76,772,233],{"class":232},[76,774,236],{"class":93},[76,776,155],{"class":93},[76,778,779,781,784,786,788,790,793,795,797,799],{"class":78,"line":158},[76,780,330],{"class":147},[76,782,783],{"class":333}," order",[76,785,169],{"class":168},[76,787,248],{"class":247},[76,789,251],{"class":93},[76,791,792],{"class":134},"findOrder",[76,794,223],{"class":178},[76,796,768],{"class":97},[76,798,236],{"class":178},[76,800,118],{"class":93},[76,802,803,805,807,809,811,813,815,817,819,821,824,826,829,831],{"class":78,"line":211},[76,804,330],{"class":147},[76,806,274],{"class":333},[76,808,169],{"class":168},[76,810,248],{"class":247},[76,812,251],{"class":93},[76,814,612],{"class":97},[76,816,251],{"class":93},[76,818,617],{"class":134},[76,820,223],{"class":178},[76,822,823],{"class":97},"order",[76,825,251],{"class":93},[76,827,828],{"class":97},"userId",[76,830,236],{"class":178},[76,832,118],{"class":93},[76,834,835,837,839,841,843,845],{"class":78,"line":216},[76,836,244],{"class":89},[76,838,94],{"class":93},[76,840,783],{"class":97},[76,842,189],{"class":93},[76,844,274],{"class":97},[76,846,363],{"class":93},[76,848,849],{"class":78,"line":241},[76,850,293],{"class":93},[76,852,853],{"class":78,"line":290},[76,854,407],{"class":93},[856,857],"hr",{},[46,859,861],{"id":860},"二自定义提供者","二、自定义提供者",[23,863,864,865,867,868,871,872,875],{},"除了类提供者（默认的 ",[41,866,43],{}," 类），NestJS 允许使用多种提供者定义方式，通过 ",[41,869,870],{},"@Module"," 装饰器的 ",[41,873,874],{},"providers"," 数组配置。",[23,877,878,879,882],{},"提供者定义的基本结构包含 ",[41,880,881],{},"provide"," 令牌（token）和具体的提供者策略。",[54,884,886,887,890],{"id":885},"_1-值提供者usevalue","1. 值提供者（",[41,888,889],{},"useValue","）",[23,892,893],{},"用于注入常量、第三方库实例或配置对象。",[67,895,897],{"className":69,"code":896,"language":71,"meta":72,"style":72},"\u002F\u002F config.module.ts\nimport { Module } from \"@nestjs\u002Fcommon\";\n\nconst config = { apiUrl: \"https:\u002F\u002Fapi.example.com\", timeout: 5000 };\n\n@Module({\n  providers: [{ provide: \"CONFIG\", useValue: config }],\n})\nexport class ConfigModule {}\n",[41,898,899,904,925,929,965,969,981,1022,1028],{"__ignoreMap":72},[76,900,901],{"class":78,"line":79},[76,902,903],{"class":82},"\u002F\u002F config.module.ts\n",[76,905,906,908,910,913,915,917,919,921,923],{"class":78,"line":86},[76,907,90],{"class":89},[76,909,94],{"class":93},[76,911,912],{"class":97}," Module",[76,914,101],{"class":93},[76,916,104],{"class":89},[76,918,108],{"class":107},[76,920,112],{"class":111},[76,922,115],{"class":107},[76,924,118],{"class":93},[76,926,927],{"class":78,"line":121},[76,928,125],{"emptyLinePlaceholder":124},[76,930,931,934,937,939,941,944,946,948,951,953,955,958,960,963],{"class":78,"line":128},[76,932,933],{"class":147},"const",[76,935,936],{"class":333}," config",[76,938,169],{"class":168},[76,940,94],{"class":93},[76,942,943],{"class":178}," apiUrl",[76,945,182],{"class":93},[76,947,108],{"class":107},[76,949,950],{"class":111},"https:\u002F\u002Fapi.example.com",[76,952,115],{"class":107},[76,954,189],{"class":93},[76,956,957],{"class":178}," timeout",[76,959,182],{"class":93},[76,961,962],{"class":185}," 5000",[76,964,363],{"class":93},[76,966,967],{"class":78,"line":141},[76,968,125],{"emptyLinePlaceholder":124},[76,970,971,973,976,978],{"class":78,"line":158},[76,972,131],{"class":93},[76,974,975],{"class":134},"Module",[76,977,223],{"class":97},[76,979,980],{"class":93},"{\n",[76,982,983,986,988,990,992,995,997,999,1002,1004,1006,1009,1011,1014,1017,1019],{"class":78,"line":211},[76,984,985],{"class":178},"  providers",[76,987,182],{"class":93},[76,989,172],{"class":97},[76,991,175],{"class":93},[76,993,994],{"class":178}," provide",[76,996,182],{"class":93},[76,998,108],{"class":107},[76,1000,1001],{"class":111},"CONFIG",[76,1003,115],{"class":107},[76,1005,189],{"class":93},[76,1007,1008],{"class":178}," useValue",[76,1010,182],{"class":93},[76,1012,1013],{"class":97}," config ",[76,1015,1016],{"class":93},"}",[76,1018,206],{"class":97},[76,1020,1021],{"class":93},",\n",[76,1023,1024,1026],{"class":78,"line":216},[76,1025,1016],{"class":93},[76,1027,511],{"class":97},[76,1029,1030,1032,1034,1037],{"class":78,"line":241},[76,1031,144],{"class":89},[76,1033,148],{"class":147},[76,1035,1036],{"class":151}," ConfigModule",[76,1038,547],{"class":93},[23,1040,1041,1042,1045],{},"在其他类中通过 ",[41,1043,1044],{},"@Inject('CONFIG')"," 注入：",[67,1047,1049],{"className":69,"code":1048,"language":71,"meta":72,"style":72},"@Injectable()\nexport class ApiService {\n  constructor(@Inject(\"CONFIG\") private config: { apiUrl: string; timeout: number }) {}\n}\n",[41,1050,1051,1059,1070,1116],{"__ignoreMap":72},[76,1052,1053,1055,1057],{"class":78,"line":79},[76,1054,131],{"class":93},[76,1056,135],{"class":134},[76,1058,138],{"class":97},[76,1060,1061,1063,1065,1068],{"class":78,"line":86},[76,1062,144],{"class":89},[76,1064,148],{"class":147},[76,1066,1067],{"class":151}," ApiService",[76,1069,155],{"class":93},[76,1071,1072,1074,1076,1079,1081,1083,1085,1087,1089,1091,1093,1095,1097,1099,1101,1103,1106,1108,1110,1112,1114],{"class":78,"line":121},[76,1073,527],{"class":147},[76,1075,577],{"class":93},[76,1077,1078],{"class":134},"Inject",[76,1080,223],{"class":97},[76,1082,115],{"class":107},[76,1084,1001],{"class":111},[76,1086,115],{"class":107},[76,1088,591],{"class":97},[76,1090,532],{"class":147},[76,1092,936],{"class":226},[76,1094,182],{"class":168},[76,1096,94],{"class":93},[76,1098,943],{"class":164},[76,1100,182],{"class":168},[76,1102,319],{"class":232},[76,1104,1105],{"class":93},";",[76,1107,957],{"class":164},[76,1109,182],{"class":168},[76,1111,233],{"class":232},[76,1113,322],{"class":93},[76,1115,547],{"class":93},[76,1117,1118],{"class":78,"line":128},[76,1119,407],{"class":93},[54,1121,1123,1124,890],{"id":1122},"_2-类提供者useclass","2. 类提供者（",[41,1125,1126],{},"useClass",[23,1128,1129],{},"允许指定某个令牌实际使用的实现类。这在需要替换实现（如测试 mock、多环境适配）时非常有用。",[67,1131,1133],{"className":69,"code":1132,"language":71,"meta":72,"style":72},"\u002F\u002F 定义抽象类或接口\nexport interface Mailer {\n  send(to: string, subject: string, body: string): void;\n}\n\nexport class SmtpMailer implements Mailer {\n  \u002F* ... *\u002F\n}\nexport class MockMailer implements Mailer {\n  \u002F* ... *\u002F\n}\n\n\u002F\u002F 模块中根据环境选择实现\n@Module({\n  providers: [\n    {\n      provide: \"MAILER\",\n      useClass: process.env.NODE_ENV === \"production\" ? SmtpMailer : MockMailer,\n    },\n  ],\n})\nexport class MailModule {}\n",[41,1134,1135,1140,1152,1193,1197,1201,1217,1222,1226,1241,1245,1249,1253,1258,1268,1277,1282,1298,1339,1345,1353,1360],{"__ignoreMap":72},[76,1136,1137],{"class":78,"line":79},[76,1138,1139],{"class":82},"\u002F\u002F 定义抽象类或接口\n",[76,1141,1142,1144,1147,1150],{"class":78,"line":86},[76,1143,144],{"class":89},[76,1145,1146],{"class":147}," interface",[76,1148,1149],{"class":151}," Mailer",[76,1151,155],{"class":93},[76,1153,1154,1157,1159,1162,1164,1166,1168,1171,1173,1175,1177,1180,1182,1184,1186,1188,1191],{"class":78,"line":121},[76,1155,1156],{"class":219},"  send",[76,1158,223],{"class":93},[76,1160,1161],{"class":226},"to",[76,1163,182],{"class":168},[76,1165,319],{"class":232},[76,1167,189],{"class":93},[76,1169,1170],{"class":226}," subject",[76,1172,182],{"class":168},[76,1174,319],{"class":232},[76,1176,189],{"class":93},[76,1178,1179],{"class":226}," body",[76,1181,182],{"class":168},[76,1183,319],{"class":232},[76,1185,236],{"class":93},[76,1187,182],{"class":168},[76,1189,1190],{"class":232}," void",[76,1192,118],{"class":93},[76,1194,1195],{"class":78,"line":128},[76,1196,407],{"class":93},[76,1198,1199],{"class":78,"line":141},[76,1200,125],{"emptyLinePlaceholder":124},[76,1202,1203,1205,1207,1210,1213,1215],{"class":78,"line":158},[76,1204,144],{"class":89},[76,1206,148],{"class":147},[76,1208,1209],{"class":151}," SmtpMailer",[76,1211,1212],{"class":147}," implements",[76,1214,1149],{"class":151},[76,1216,155],{"class":93},[76,1218,1219],{"class":78,"line":211},[76,1220,1221],{"class":82},"  \u002F* ... *\u002F\n",[76,1223,1224],{"class":78,"line":216},[76,1225,407],{"class":93},[76,1227,1228,1230,1232,1235,1237,1239],{"class":78,"line":241},[76,1229,144],{"class":89},[76,1231,148],{"class":147},[76,1233,1234],{"class":151}," MockMailer",[76,1236,1212],{"class":147},[76,1238,1149],{"class":151},[76,1240,155],{"class":93},[76,1242,1243],{"class":78,"line":290},[76,1244,1221],{"class":82},[76,1246,1247],{"class":78,"line":296},[76,1248,407],{"class":93},[76,1250,1251],{"class":78,"line":301},[76,1252,125],{"emptyLinePlaceholder":124},[76,1254,1255],{"class":78,"line":327},[76,1256,1257],{"class":82},"\u002F\u002F 模块中根据环境选择实现\n",[76,1259,1260,1262,1264,1266],{"class":78,"line":366},[76,1261,131],{"class":93},[76,1263,975],{"class":134},[76,1265,223],{"class":97},[76,1267,980],{"class":93},[76,1269,1270,1272,1274],{"class":78,"line":390},[76,1271,985],{"class":178},[76,1273,182],{"class":93},[76,1275,1276],{"class":97}," [\n",[76,1278,1279],{"class":78,"line":399},[76,1280,1281],{"class":93},"    {\n",[76,1283,1284,1287,1289,1291,1294,1296],{"class":78,"line":404},[76,1285,1286],{"class":178},"      provide",[76,1288,182],{"class":93},[76,1290,108],{"class":107},[76,1292,1293],{"class":111},"MAILER",[76,1295,115],{"class":107},[76,1297,1021],{"class":93},[76,1299,1300,1303,1305,1308,1310,1313,1315,1318,1320,1322,1325,1327,1330,1333,1335,1337],{"class":78,"line":701},[76,1301,1302],{"class":178},"      useClass",[76,1304,182],{"class":93},[76,1306,1307],{"class":97}," process",[76,1309,251],{"class":93},[76,1311,1312],{"class":97},"env",[76,1314,251],{"class":93},[76,1316,1317],{"class":333},"NODE_ENV",[76,1319,281],{"class":168},[76,1321,108],{"class":107},[76,1323,1324],{"class":111},"production",[76,1326,115],{"class":107},[76,1328,1329],{"class":168}," ?",[76,1331,1332],{"class":97}," SmtpMailer ",[76,1334,182],{"class":168},[76,1336,1234],{"class":97},[76,1338,1021],{"class":93},[76,1340,1342],{"class":78,"line":1341},19,[76,1343,1344],{"class":93},"    },\n",[76,1346,1348,1351],{"class":78,"line":1347},20,[76,1349,1350],{"class":97},"  ]",[76,1352,1021],{"class":93},[76,1354,1356,1358],{"class":78,"line":1355},21,[76,1357,1016],{"class":93},[76,1359,511],{"class":97},[76,1361,1363,1365,1367,1370],{"class":78,"line":1362},22,[76,1364,144],{"class":89},[76,1366,148],{"class":147},[76,1368,1369],{"class":151}," MailModule",[76,1371,547],{"class":93},[54,1373,1375,1376,890],{"id":1374},"_3-工厂提供者usefactory","3. 工厂提供者（",[41,1377,1378],{},"useFactory",[23,1380,1381,1382,36],{},"动态创建实例，支持依赖其他提供者。工厂可以是异步的，返回 ",[41,1383,1384],{},"Promise",[67,1386,1388],{"className":69,"code":1387,"language":71,"meta":72,"style":72},"@Module({\n  providers: [\n    {\n      provide: \"DATABASE_CONNECTION\",\n      useFactory: async (configService: ConfigService) => {\n        const dbConfig = configService.getDatabaseConfig();\n        const connection = await createDatabaseConnection(dbConfig);\n        return connection;\n      },\n      inject: [ConfigService], \u002F\u002F 注入依赖，数组中顺序对应工厂函数参数\n    },\n  ],\n})\nexport class DatabaseModule {}\n",[41,1389,1390,1400,1408,1412,1427,1454,1476,1500,1509,1514,1529,1533,1539,1545],{"__ignoreMap":72},[76,1391,1392,1394,1396,1398],{"class":78,"line":79},[76,1393,131],{"class":93},[76,1395,975],{"class":134},[76,1397,223],{"class":97},[76,1399,980],{"class":93},[76,1401,1402,1404,1406],{"class":78,"line":86},[76,1403,985],{"class":178},[76,1405,182],{"class":93},[76,1407,1276],{"class":97},[76,1409,1410],{"class":78,"line":121},[76,1411,1281],{"class":93},[76,1413,1414,1416,1418,1420,1423,1425],{"class":78,"line":128},[76,1415,1286],{"class":178},[76,1417,182],{"class":93},[76,1419,108],{"class":107},[76,1421,1422],{"class":111},"DATABASE_CONNECTION",[76,1424,115],{"class":107},[76,1426,1021],{"class":93},[76,1428,1429,1432,1434,1437,1440,1443,1445,1448,1450,1452],{"class":78,"line":141},[76,1430,1431],{"class":134},"      useFactory",[76,1433,182],{"class":93},[76,1435,1436],{"class":147}," async",[76,1438,1439],{"class":93}," (",[76,1441,1442],{"class":226},"configService",[76,1444,182],{"class":168},[76,1446,1447],{"class":151}," ConfigService",[76,1449,236],{"class":93},[76,1451,271],{"class":147},[76,1453,155],{"class":93},[76,1455,1456,1459,1462,1464,1467,1469,1472,1474],{"class":78,"line":158},[76,1457,1458],{"class":147},"        const",[76,1460,1461],{"class":333}," dbConfig",[76,1463,169],{"class":168},[76,1465,1466],{"class":97}," configService",[76,1468,251],{"class":93},[76,1470,1471],{"class":134},"getDatabaseConfig",[76,1473,353],{"class":178},[76,1475,118],{"class":93},[76,1477,1478,1480,1483,1485,1488,1491,1493,1496,1498],{"class":78,"line":211},[76,1479,1458],{"class":147},[76,1481,1482],{"class":333}," connection",[76,1484,169],{"class":168},[76,1486,1487],{"class":89}," await",[76,1489,1490],{"class":134}," createDatabaseConnection",[76,1492,223],{"class":178},[76,1494,1495],{"class":97},"dbConfig",[76,1497,236],{"class":178},[76,1499,118],{"class":93},[76,1501,1502,1505,1507],{"class":78,"line":216},[76,1503,1504],{"class":89},"        return",[76,1506,1482],{"class":97},[76,1508,118],{"class":93},[76,1510,1511],{"class":78,"line":241},[76,1512,1513],{"class":93},"      },\n",[76,1515,1516,1519,1521,1524,1526],{"class":78,"line":290},[76,1517,1518],{"class":178},"      inject",[76,1520,182],{"class":93},[76,1522,1523],{"class":97}," [ConfigService]",[76,1525,189],{"class":93},[76,1527,1528],{"class":82}," \u002F\u002F 注入依赖，数组中顺序对应工厂函数参数\n",[76,1530,1531],{"class":78,"line":296},[76,1532,1344],{"class":93},[76,1534,1535,1537],{"class":78,"line":301},[76,1536,1350],{"class":97},[76,1538,1021],{"class":93},[76,1540,1541,1543],{"class":78,"line":327},[76,1542,1016],{"class":93},[76,1544,511],{"class":97},[76,1546,1547,1549,1551,1554],{"class":78,"line":366},[76,1548,144],{"class":89},[76,1550,148],{"class":147},[76,1552,1553],{"class":151}," DatabaseModule",[76,1555,547],{"class":93},[23,1557,1558,1559,1562],{},"使用工厂时，",[41,1560,1561],{},"inject"," 数组用于声明需要哪些提供者作为工厂参数。",[54,1564,1566,1567,890],{"id":1565},"_4-别名提供者useexisting","4. 别名提供者（",[41,1568,1569],{},"useExisting",[23,1571,1572],{},"为已有的提供者创建一个别名，使得可以通过不同令牌注入同一个实例。",[67,1574,1576],{"className":69,"code":1575,"language":71,"meta":72,"style":72},"@Module({\n  providers: [SomeService, { provide: \"ALIAS_SERVICE\", useExisting: SomeService }],\n})\nexport class MyModule {}\n",[41,1577,1578,1588,1628,1634],{"__ignoreMap":72},[76,1579,1580,1582,1584,1586],{"class":78,"line":79},[76,1581,131],{"class":93},[76,1583,975],{"class":134},[76,1585,223],{"class":97},[76,1587,980],{"class":93},[76,1589,1590,1592,1594,1597,1599,1601,1603,1605,1607,1610,1612,1614,1617,1619,1622,1624,1626],{"class":78,"line":86},[76,1591,985],{"class":178},[76,1593,182],{"class":93},[76,1595,1596],{"class":97}," [SomeService",[76,1598,189],{"class":93},[76,1600,94],{"class":93},[76,1602,994],{"class":178},[76,1604,182],{"class":93},[76,1606,108],{"class":107},[76,1608,1609],{"class":111},"ALIAS_SERVICE",[76,1611,115],{"class":107},[76,1613,189],{"class":93},[76,1615,1616],{"class":178}," useExisting",[76,1618,182],{"class":93},[76,1620,1621],{"class":97}," SomeService ",[76,1623,1016],{"class":93},[76,1625,206],{"class":97},[76,1627,1021],{"class":93},[76,1629,1630,1632],{"class":78,"line":121},[76,1631,1016],{"class":93},[76,1633,511],{"class":97},[76,1635,1636,1638,1640,1643],{"class":78,"line":128},[76,1637,144],{"class":89},[76,1639,148],{"class":147},[76,1641,1642],{"class":151}," MyModule",[76,1644,547],{"class":93},[23,1646,1647,1648,1651,1652,1655],{},"此时，",[41,1649,1650],{},"'ALIAS_SERVICE'"," 和 ",[41,1653,1654],{},"SomeService"," 令牌指向同一个实例。",[46,1657,1659],{"id":1658},"三异步提供者","三、异步提供者",[23,1661,1662,1663,1666,1667,1669],{},"如果提供者的初始化需要异步操作（如数据库连接、HTTP 请求），可以使用 ",[41,1664,1665],{},"async"," 工厂函数或返回 ",[41,1668,1384],{}," 的值提供者。",[23,1671,1672],{},"NestJS 会等待异步提供者解析完成，才注入到依赖该提供者的其他类中。",[67,1674,1676],{"className":69,"code":1675,"language":71,"meta":72,"style":72},"@Module({\n  providers: [\n    {\n      provide: \"ASYNC_DB\",\n      useFactory: async () => {\n        const connection = await orm.createConnection();\n        return connection;\n      },\n    },\n  ],\n})\nexport class AppModule {}\n",[41,1677,1678,1688,1696,1700,1715,1730,1752,1760,1764,1768,1774,1780],{"__ignoreMap":72},[76,1679,1680,1682,1684,1686],{"class":78,"line":79},[76,1681,131],{"class":93},[76,1683,975],{"class":134},[76,1685,223],{"class":97},[76,1687,980],{"class":93},[76,1689,1690,1692,1694],{"class":78,"line":86},[76,1691,985],{"class":178},[76,1693,182],{"class":93},[76,1695,1276],{"class":97},[76,1697,1698],{"class":78,"line":121},[76,1699,1281],{"class":93},[76,1701,1702,1704,1706,1708,1711,1713],{"class":78,"line":128},[76,1703,1286],{"class":178},[76,1705,182],{"class":93},[76,1707,108],{"class":107},[76,1709,1710],{"class":111},"ASYNC_DB",[76,1712,115],{"class":107},[76,1714,1021],{"class":93},[76,1716,1717,1719,1721,1723,1726,1728],{"class":78,"line":141},[76,1718,1431],{"class":134},[76,1720,182],{"class":93},[76,1722,1436],{"class":147},[76,1724,1725],{"class":93}," ()",[76,1727,271],{"class":147},[76,1729,155],{"class":93},[76,1731,1732,1734,1736,1738,1740,1743,1745,1748,1750],{"class":78,"line":158},[76,1733,1458],{"class":147},[76,1735,1482],{"class":333},[76,1737,169],{"class":168},[76,1739,1487],{"class":89},[76,1741,1742],{"class":97}," orm",[76,1744,251],{"class":93},[76,1746,1747],{"class":134},"createConnection",[76,1749,353],{"class":178},[76,1751,118],{"class":93},[76,1753,1754,1756,1758],{"class":78,"line":211},[76,1755,1504],{"class":89},[76,1757,1482],{"class":97},[76,1759,118],{"class":93},[76,1761,1762],{"class":78,"line":216},[76,1763,1513],{"class":93},[76,1765,1766],{"class":78,"line":241},[76,1767,1344],{"class":93},[76,1769,1770,1772],{"class":78,"line":290},[76,1771,1350],{"class":97},[76,1773,1021],{"class":93},[76,1775,1776,1778],{"class":78,"line":296},[76,1777,1016],{"class":93},[76,1779,511],{"class":97},[76,1781,1782,1784,1786,1789],{"class":78,"line":301},[76,1783,144],{"class":89},[76,1785,148],{"class":147},[76,1787,1788],{"class":151}," AppModule",[76,1790,547],{"class":93},[46,1792,1794,1795,890],{"id":1793},"四可选提供者optional","四、可选提供者（",[41,1796,1797],{},"@Optional()",[23,1799,1800,1801,1803,1804,1807],{},"当某个依赖不是必须存在时，可以使用 ",[41,1802,1797],{}," 装饰器。如果该提供者未注册，注入的值会是 ",[41,1805,1806],{},"undefined","，而不会抛出错误。",[67,1809,1811],{"className":69,"code":1810,"language":71,"meta":72,"style":72},"@Injectable()\nexport class LoggerService {\n  constructor(@Optional() private readonly config?: ConfigService) {\n    if (config) {\n      \u002F\u002F 使用 config 配置日志级别\n    } else {\n      \u002F\u002F 使用默认配置\n    }\n  }\n}\n",[41,1812,1813,1821,1832,1858,1872,1877,1887,1892,1897,1901],{"__ignoreMap":72},[76,1814,1815,1817,1819],{"class":78,"line":79},[76,1816,131],{"class":93},[76,1818,135],{"class":134},[76,1820,138],{"class":97},[76,1822,1823,1825,1827,1830],{"class":78,"line":86},[76,1824,144],{"class":89},[76,1826,148],{"class":147},[76,1828,1829],{"class":151}," LoggerService",[76,1831,155],{"class":93},[76,1833,1834,1836,1838,1841,1843,1845,1847,1849,1852,1854,1856],{"class":78,"line":121},[76,1835,527],{"class":147},[76,1837,577],{"class":93},[76,1839,1840],{"class":134},"Optional",[76,1842,654],{"class":97},[76,1844,532],{"class":147},[76,1846,535],{"class":147},[76,1848,936],{"class":226},[76,1850,1851],{"class":168},"?:",[76,1853,1447],{"class":151},[76,1855,236],{"class":93},[76,1857,155],{"class":93},[76,1859,1860,1863,1865,1868,1870],{"class":78,"line":128},[76,1861,1862],{"class":89},"    if",[76,1864,1439],{"class":178},[76,1866,1867],{"class":97},"config",[76,1869,591],{"class":178},[76,1871,980],{"class":93},[76,1873,1874],{"class":78,"line":141},[76,1875,1876],{"class":82},"      \u002F\u002F 使用 config 配置日志级别\n",[76,1878,1879,1882,1885],{"class":78,"line":158},[76,1880,1881],{"class":93},"    }",[76,1883,1884],{"class":89}," else",[76,1886,155],{"class":93},[76,1888,1889],{"class":78,"line":211},[76,1890,1891],{"class":82},"      \u002F\u002F 使用默认配置\n",[76,1893,1894],{"class":78,"line":216},[76,1895,1896],{"class":93},"    }\n",[76,1898,1899],{"class":78,"line":241},[76,1900,293],{"class":93},[76,1902,1903],{"class":78,"line":290},[76,1904,407],{"class":93},[46,1906,1908],{"id":1907},"五提供者的作用域","五、提供者的作用域",[23,1910,1911,1912,1915,1916,1919],{},"提供者默认是单例（SINGLETON）作用域，即整个应用共享同一个实例。但也可以通过 ",[41,1913,1914],{},"@Injectable({ scope: Scope.REQUEST })"," 或 ",[41,1917,1918],{},"Scope.TRANSIENT"," 改变作用域。详细内容已在“模块系统与依赖注入”中介绍。",[46,1921,1923],{"id":1922},"六自定义提供者的令牌类型","六、自定义提供者的令牌类型",[23,1925,1926,1927,1929],{},"提供者的 ",[41,1928,881],{}," 令牌可以是：",[1931,1932,1933,1940,1946],"ul",{},[1934,1935,1936,1937,890],"li",{},"字符串或 Symbol（如上例 ",[41,1938,1939],{},"'CONFIG'",[1934,1941,1942,1943,1945],{},"类本身（默认情况，",[41,1944,1126],{}," 或简写时）",[1934,1947,1948],{},"抽象类或接口（但在 JavaScript 中无法直接使用接口，需要借助字符串或 Symbol）",[23,1950,1951],{},"为了获得更好的类型安全，推荐使用自定义符号或类作为令牌。",[67,1953,1955],{"className":69,"code":1954,"language":71,"meta":72,"style":72},"export const DATABASE_CONNECTION = Symbol('DATABASE_CONNECTION');\n\n\u002F\u002F 在 provider 中使用\n{ provide: DATABASE_CONNECTION, useFactory: ... }\n\n\u002F\u002F 注入时\n@Inject(DATABASE_CONNECTION) private connection: Connection\n",[41,1956,1957,1985,1989,1994,2016,2020,2025],{"__ignoreMap":72},[76,1958,1959,1961,1964,1967,1969,1972,1974,1977,1979,1981,1983],{"class":78,"line":79},[76,1960,144],{"class":89},[76,1962,1963],{"class":147}," const",[76,1965,1966],{"class":333}," DATABASE_CONNECTION",[76,1968,169],{"class":168},[76,1970,1971],{"class":134}," Symbol",[76,1973,223],{"class":97},[76,1975,1976],{"class":107},"'",[76,1978,1422],{"class":111},[76,1980,1976],{"class":107},[76,1982,236],{"class":97},[76,1984,118],{"class":93},[76,1986,1987],{"class":78,"line":86},[76,1988,125],{"emptyLinePlaceholder":124},[76,1990,1991],{"class":78,"line":121},[76,1992,1993],{"class":82},"\u002F\u002F 在 provider 中使用\n",[76,1995,1996,1998,2000,2002,2004,2006,2009,2011,2013],{"class":78,"line":128},[76,1997,175],{"class":93},[76,1999,994],{"class":151},[76,2001,182],{"class":93},[76,2003,1966],{"class":333},[76,2005,189],{"class":93},[76,2007,2008],{"class":151}," useFactory",[76,2010,182],{"class":93},[76,2012,358],{"class":168},[76,2014,2015],{"class":93}," }\n",[76,2017,2018],{"class":78,"line":141},[76,2019,125],{"emptyLinePlaceholder":124},[76,2021,2022],{"class":78,"line":158},[76,2023,2024],{"class":82},"\u002F\u002F 注入时\n",[76,2026,2027,2029,2031,2033,2035,2038,2041,2043],{"class":78,"line":211},[76,2028,131],{"class":93},[76,2030,1078],{"class":134},[76,2032,223],{"class":97},[76,2034,1422],{"class":333},[76,2036,2037],{"class":97},") private ",[76,2039,2040],{"class":151},"connection",[76,2042,182],{"class":93},[76,2044,2045],{"class":97}," Connection\n",[46,2047,2048],{"id":2048},"总结",[2050,2051,2052,2068],"table",{},[2053,2054,2055],"thead",{},[2056,2057,2058,2062,2065],"tr",{},[2059,2060,2061],"th",{},"提供者类型",[2059,2063,2064],{},"使用方式",[2059,2066,2067],{},"适用场景",[2069,2070,2071,2089,2101,2113,2128,2140,2155],"tbody",{},[2056,2072,2073,2077,2086],{},[2074,2075,2076],"td",{},"类提供者（服务）",[2074,2078,2079,2080,2082,2083,2085],{},"默认 ",[41,2081,43],{},"，在 ",[41,2084,874],{}," 中直接添加类",[2074,2087,2088],{},"专注业务逻辑、可复用的服务",[2056,2090,2091,2094,2098],{},[2074,2092,2093],{},"值提供者",[2074,2095,2096],{},[41,2097,889],{},[2074,2099,2100],{},"常量、配置对象、第三方库实例",[2056,2102,2103,2106,2110],{},[2074,2104,2105],{},"类提供者（替换）",[2074,2107,2108],{},[41,2109,1126],{},[2074,2111,2112],{},"接口的不同实现（mock、生产环境）",[2056,2114,2115,2118,2125],{},[2074,2116,2117],{},"工厂提供者",[2074,2119,2120,2122,2123],{},[41,2121,1378],{}," + ",[41,2124,1561],{},[2074,2126,2127],{},"需要依赖其他提供者创建实例",[2056,2129,2130,2133,2137],{},[2074,2131,2132],{},"别名提供者",[2074,2134,2135],{},[41,2136,1569],{},[2074,2138,2139],{},"同一实例不同令牌访问",[2056,2141,2142,2145,2152],{},[2074,2143,2144],{},"异步提供者",[2074,2146,2147,2149,2150],{},[41,2148,1378],{}," 返回 ",[41,2151,1384],{},[2074,2153,2154],{},"数据库连接、初始化外部资源",[2056,2156,2157,2160,2164],{},[2074,2158,2159],{},"可选提供者",[2074,2161,2162,60],{},[41,2163,1797],{},[2074,2165,2166],{},"依赖非必需的情况",[23,2168,2169],{},"理解这些提供者形式，可以灵活管理应用中的各种依赖，让 NestJS 应用更加模块化和可测试。",[2171,2172,2173],"h2",{"id":2173},"参考文献",[23,2175,2176],{},"以下链接在编写时均可正常访问：",[2050,2178,2179,2189],{},[2053,2180,2181],{},[2056,2182,2183,2186],{},[2059,2184,2185],{},"资料",[2059,2187,2188],{},"说明",[2069,2190,2191,2204,2216],{},[2056,2192,2193,2201],{},[2074,2194,2195],{},[32,2196,2200],{"href":2197,"rel":2198},"https:\u002F\u002Fdocs.nestjs.com\u002F",[2199],"nofollow","NestJS 文档",[2074,2202,2203],{},"官方",[2056,2205,2206,2213],{},[2074,2207,2208],{},[32,2209,2212],{"href":2210,"rel":2211},"https:\u002F\u002Fdocs.nestjs.com\u002Fproviders",[2199],"Providers",[2074,2214,2215],{},"本章主题",[2056,2217,2218,2225],{},[2074,2219,2220],{},[32,2221,2224],{"href":2222,"rel":2223},"https:\u002F\u002Fdocs.nestjs.com\u002Ffaq\u002Frequest-lifecycle",[2199],"Request lifecycle",[2074,2226,2227],{},"执行顺序",[2229,2230,2231],"style",{},"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 .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 .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--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 .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 .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--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 .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);}",{"title":72,"searchDepth":86,"depth":86,"links":2233},[2234,2235,2236,2237,2239,2240,2241,2242],{"id":48,"depth":121,"text":49},{"id":860,"depth":121,"text":861},{"id":1658,"depth":121,"text":1659},{"id":1793,"depth":121,"text":2238},"四、可选提供者（@Optional()）",{"id":1907,"depth":121,"text":1908},{"id":1922,"depth":121,"text":1923},{"id":2048,"depth":121,"text":2048},{"id":2173,"depth":86,"text":2173},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fservice","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fservice.md","md",{"items":2248},[2249,2253,2257,2261,2265,2269],{"path":2250,"title":2251,"description":2252,"category":10,"score":158},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fauth","认证与授权","认证（Authentication）：确认「你是谁」（如 JWT、Session）。 - 授权（Authorization）：确认「你能做什么」（如 RBAC、策略检查）。",{"path":2254,"title":2255,"description":2256,"category":10,"score":158},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache","缓存","@nestjs\u002Fcache-manager 统一缓存 API，存储实现可插拔。",{"path":2258,"title":2259,"description":2260,"category":10,"score":158},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fguards","守卫 (Guards) 与授权","守卫决定是否放行请求，常用于认证与授权。见 auth。",{"path":2262,"title":2263,"description":2264,"category":10,"score":158},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fconfig","配置管理（Config 模块）","@nestjs\u002Fconfig 加载 .env 并提供 ConfigService。见 工程化 env。",{"path":2266,"title":2267,"description":2268,"category":10,"score":158},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdatabase","数据库集成（以 TypeORM 为例）","Nest 通过 @nestjs\u002Ftypeorm 等包集成 ORM；生产环境用 migration，慎用 synchronize。亦可选用 Prisma、MikroORM 等（见 官方 Database）。",{"path":2270,"title":2271,"description":2272,"category":10,"score":158},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcron","定时任务","@nestjs\u002Fschedule 基于 cron 表达式调度任务。",{"series":2274,"title":2275,"items":2276,"index":404,"prev":2336,"next":2337},"booklet\u002Fend\u002Fnestjs\u002Fnew","new",[2277,2279,2283,2285,2287,2291,2293,2297,2299,2303,2307,2309,2313,2317,2321,2324,2327,2331,2332],{"path":2250,"title":2251,"date":2278,"pinned":15},"2025-12-23",{"path":2280,"title":2281,"date":2282,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase","NestJS 基础","2021-03-09",{"path":2254,"title":2255,"date":2284,"pinned":15},"2025-07-04",{"path":2262,"title":2263,"date":2286,"pinned":15},"2023-08-26",{"path":2288,"title":2289,"date":2290,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcontroller","控制器与路由","2020-07-18",{"path":2270,"title":2271,"date":2292,"pinned":15},"2023-04-12",{"path":2294,"title":2295,"date":2296,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcustom-decorators","自定义装饰器","2021-09-19",{"path":2266,"title":2267,"date":2298,"pinned":15},"2023-05-26",{"path":2300,"title":2301,"date":2302,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdeploy","部署与运维","2023-01-24",{"path":2304,"title":2305,"date":2306,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Ferror","异常处理","2020-01-28",{"path":2258,"title":2259,"date":2308,"pinned":15},"2023-09-09",{"path":2310,"title":2311,"date":2312,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept","拦截器 (Interceptors)","2021-04-26",{"path":2314,"title":2315,"date":2316,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger","日志记录","2022-10-10",{"path":2318,"title":2319,"date":2320,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmiddleware","中间件 (Middleware)","2021-11-26",{"path":34,"title":2322,"date":2323,"pinned":15},"模块系统与依赖注入","2022-06-15",{"path":2325,"title":2326,"date":2290,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fpipes","管道 (Pipes) 与数据验证",{"path":2328,"title":2329,"date":2330,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fqueue","队列（Bull）","2021-07-01",{"path":7,"title":8,"date":14,"pinned":15},{"path":2333,"title":2334,"date":2335,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fwebsocket","WebSocket（网关）","2022-12-14",{"path":2328,"title":2329,"date":2330,"pinned":15},{"path":2333,"title":2334,"date":2335,"pinned":15}]