作为一名程序员,离不来英语,软件官方文档,顶会期刊和论文,基本都是英语。
而且英语是一门形式化语言,比如被动,现在、过去、将来等即就是时态语态可以从
英语表达的形式上体现出来。比较容易能看出来描述的主体的逻辑关系,这对于学习
程序概念学习是有益处。恰好最近正在学,也是探索和尝试一种学习英语的方式。
We'll take an overview of Nest.js
and
look at
the core concepts
- that you'll need to build a Nest.js application.
- take an overview
- 在这个语境下,
take本身没有拿取的意思,而是与后面的名词组合来形成一个特定的意思
- 意思是:对某事或某物进行一个总体的、概括性的查看或审视
- 近似于
- have a general look
- get a broad perspective
take可与多种名词搭配,形成各种意思
- take a look: 看一下
- take a break: 休息一下
- take a shower: 洗个脸
- take a chance: 冒个险
- build a Nest.js application
Nest中的Controller负责(resposible for)处理传入请求(incoming requests)并向客户端返回响应(returning responses)
Nest会将**传入请求(incoming request)**路由(route)到控制器类(Controller)中的处理函数(handler function)
我们使用@Controller()装饰器(decorotor)来创建一个控制器类
import { Controller, Get } from '@nestjs/common'
@Controller
export class EnteryController {
@Get
index(): Entry[] {
const entries: Entry[] = this.entriesService.findAll()
return entries
}
}
- Controllers in Nest
-
responsible for
- phrasal verb
- 描述某事或某物的职责或功能
- handling incoming request and returning response
- route incoming requests
- handler function
- controller classes
@Controller decorator
Providers in Nest
are used to
create
- services
- factories
- helper
- and more
- that can be injected into controllers
- and other providers
- using Nest's built-in dependency injection
The @Injectable() decorator is used to create a provider class.
Nest中的provider用于创建services、factories、helpers
这些services、factories、helpers可以使用Nest内置的依赖注入到控制器和其他provider中。
@Injectable()装饰器用于创建a provider class
我们博客应用中的AuthenticationService事一个注入并使用UsersService组件的提供程序
@Injectable
export class AuthenticationService {
constructor(private readonly userService: UserService) {}
async validateUser(payload: { email: string; password: string;}): Promise<boolean> {
const user = await this.userService.findOne({where: {email: payload.email }})
return !!user
}
}
-
are(be) used to
- Providers in Nest
-
used to create
- 表示用于创建或制造某物
- used to create a provider class
- service, factories, helpers, and more
-
can be injected into
- Nest's built-in dependency injection
- built-in: ...内置...
- dependency injection: 依赖注入
A Nest.js application is organized into modules.
Every Nest.js application will have a root module
-
In a small application
- this may be the only module.
-
In a larger application
- it makes sense to organize your application into multiple modules
- that split up your code into features and related capabilities
-
A module in Nest.js
-
is a class
- with a @Module() decorator.
-
The @Module() decorator
- takes a single object
- that describes module using the following properties.
- components
- controllers
- imports
- exports
-
components
- The components to be instantiated
- that may be shared across this module
- and exported to be available to other modules
-
controllers
- The controllers that are created by this module
-
imports
- The list of modules to import that export components
- that are requires in this module
-
exports
- The list of components from this module
- to be made available to other modules
-
The AppModule imports the modules
- that are needed for the application.
-
The root module in our application
- doesn't need to have any
exports
- since no other modulers import it
-
The root module also doesn't need to have any exports
- since no other modules import it
-
The root module doesn't have any conponents or controllers
- as these are all organized within the sub-modules they are related to
-
Modules in Nest.js are singletons by default.
- This means that you can share the same instance of an exported component
每个Nest.js应用被组织成模块。
每个Nest.js都有一个根模块
在小型应用中,根模块可能是唯一的模块
在大型应用程序中,应用程序被组织成多个模块,这些模块将代码分割成不同的功能和相关能力
Nest.js中的模块是带有@Module()装饰器的类。
在根模块AppModule中包含多个模块处理认证、评论、数据库访问、博客条目和用户
@Module({
components: [],
controllders: [],
imports: [
DatabaseModule,
AuthenticationModule.forRoot('jwt'),
UserModule,
EntryModule,
CommentModule,
UserGatewayModule,
CommentGatewayModule
],
exports: [],
})
export class AppModule implements NestModule {}
The EntryModule
@Module({
components: [entryProvider, EntryService],
controllers: [EnteryController],
imports: [],
exports: [EntryService]
})
export class EntryModule implements NestModule {}
-
is organized into
- 被动语态的动词短语
- 某 物或某事被安排活组织成某种形式或结构
- 整体 be organized into 部分
-
to organize ... into ...
-
split up
- phrasal verb
- 分割或分离成若干部分
- to split up 整体 into 部分
- The teacher decided to split up the students into small groups for the project
-
features and related capabilities
-
module in Nest.js
-
@Module decorator
-
take a single object
-
components to be instantiated
-
available to other modulers
-
controller that are created by this module
-
list of modules to import
-
list of components from this module
-
components that are required in this module
-
since ...
-
as ...
- Every Nest.js application**
- needs to be bootstrapped.
- This is done by byusing the NestFactory
- to create the root module and calling the listen() method.
每个Nest.js应用都需要引导(bootstrapped),这是通过使用NestFactory创建根模块并调用listen()method.
应用程序的入口是main.ts,使用async/await模式来创建AppModule并调用listen()
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'
async function bootstrap() {
const app = await NestFactory.create(AppModule)
await app.listen(3000)
}
Nest.js中间件是一个函数或一个使用@Injectable装饰的类,它实现了NestMiddleware接口。
中间件在路由处理程序之前被调用。
这些函数可以访问请求和响应对象,并对请求和响应对象进行更改
可以为路由配置一个或多个中间件函数,
并且中间件函数可以选择将执行传递给栈上的下一个中间件函数或结束请求-响应周期
如果中间件函数没有结束请求-响应周期
则它必须调用next()将控制权传递给下一个中间件函数或请求处理程序(栈上最后一个中间件函数)
如果不是按照上面的方式执行,请求会被挂起。
中间件是在Nest.js模块的configure()函数中的路由上配置的。
博客应用程序中的AuthenticationMiddleware负责对访问博客的用户进行身份验证。
import { MiddlewareFunction } from '@nestjs/common'
import { HttpState } from '@nestjs/common'
import { Injectable } from '@nestjs/common'
import { NestMiddleware } from '@nestjs/common'
import * as passport from 'passport'
import { UserService } from '../../modules/user/user.service'
@Injectable
export class AuthenticationMiddleware implements NestMiddleware {
constructor(private userService: UserService) {}
async resolve(strategy: string): Promise<MiddlewareFunction> {
return async (req, res, next) => {
return passport.authenticate(strategy, async (...args: any[]) => {
const [, payploy, err] = args
if (err) {
return res
.status(HttpState.BAD_REQUEST)
.send('Unable to authenticate the user.')
}
const user = await this.userService.findOne({
where: { email: payload.email }
})
req.user = user
return next()
})(req, res, next)
}
}
}
-
如果身份验证失败
-
如果身份验证成功
- 则调用
next(),请求将继续沿着中间件栈 向下传输 ,直到到达请求处理程序
AuthenticationMiddle在AppModule中配置,如下:
@Module({
imports: [
DatabaseModule,
AuthenticationMiddle.forRoot('jwt'),
UserModule,
EntryModule,
CommentModule,
UserGatewayModule,
CommentGatewayModule,
KeywordModule,
],
controllders: [],
providers: []
})
export class AppModule implements NestModule{
public configure(consumer: MiddlewareConsumer) {
const userControllerAuthenticateRoutes = [
{ path: '/user', method: RequestMethod.GET },
{ path: '/user/:id', method: RequestMethod.GET },
{ path: '/user/:id', method: RequestMethod.PUT },
{ path: '/user/:id', method: RequestMethod.DELETE },
]
consumer
.apply(AuthenticationMiddle)
.with(strategy)
.forRoutes(
...userControllerAuthenticateRoutes,
EnteryController,
CommentModule
)
}
}
- 可以将中间件应用于控制器上的所有路由
- 就像对
EntryController和CommentController所做的那样。
- 还可以按路径将中间件应用于特定路由
- 就像对
UserController中的路由子集所做的那样
-
Guards
- are classes
- that are decorated with the
@Injectable() decorator
- and implements the
CanActivate interface
-
A guard
- is responsible for determining
- if a request should be handled by a route handler or route.
-
Guards
- are executed
- after every middleware
- but before pipes
-
Unlike middleware
- guards have access to the
ExecutionContext object
- so they know exectly what is going to evaluated
-
The @UseGuards decorator
- is used to apply a guard to a route
- This decorator can be used on a controller class
- to apply the guard to all routes in that controller
Guard(守护程序)是使用@Injectable()装饰器装饰并实现CanActivate接口的类。
Guards负责确定请求应有程序处理器还是路由来处理。
Guards在每个中间件之后,但在管道之前执行。
-
与中间件不同的是
- Guards可以访问
ExecutionContext对象
- 因此它们能准确知道将要求值的内容
-
@UseGuards装饰器
- 被用于对路由(route)应用保护(guard)
- 以便将防护措施应用与该控制器中的所有路由
- 可以再控制器中的单个路由处理程序,如
UserController所示
在博客程序中,我们在UserController中使用CheckLoggedInUserGuard来只允许某个用户访问和访问自己的用户信息。
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'
import { Observable } from 'rxjs'
@Injectable()
export class CheckLoggedInUserGuard implements CanActivate {
canActivate(
context: ExecutionContext
): boolean | Promise<boolean> | Observable<boolean> {
const req = context.switchToHttp().getRequest()
return Number(req.params.userId) === req.user.id
}
}
@Controller('users')
export class UserController {
constructor(private readonly userService: UserSevice) {}
@Get(':userId')
@UseGuards(CheckLoggedInUserGuard)
show(@Param('userId') userId: number) {
const user: User = this.userService.findById(userId)
return user
}
}
-
decorated with
-
implement the CanActivate interface
-
responsible for determing
-
handled by a route handler or route
-
executed after every middleware
-
but before pipes
-
Unlike middleware
-
have access to
-
know exactly what
-
is going to evaluated
-
used to apply
-
a guard to a route
-
used on a controller class
-
apply the guard
-
all routes in that controller
-
individual route handlers
-
in a controller
-
as seen in the UserController
-
Nest.js application
-
Modules
- is organized into modules
- have a root module
- split up your code into feature and related capabilities
-
is a class
- decorated with
@Module decorator
- describes module using properties
- components
- controllers
- imports
- exports
-
Controllers
-
are responsible for
- handing incoming requests
- and returning responses to client
- route
- incoming request to handler functions
-
Providers
-
are used to create
- services
- factories
- helpers
- can be injected into controllers
- other providers
-
to create a provider class
- using
@Injectable() decorator
-
Middleware
- is
- either a function
- or a class
- decorated with
Injectable()
- implements the
NestMiddleware interface
- have access to
- request object
- and response object
- makes changes to
- request object
- and response object
- can be configured for a route
- in the
configure() function
- a middleware function
- choose to pass the execution
- to the next middleware function on stack
- call
next() to pass control
- or to end the request-response cycle
-
Guards
- are classes that
- are decorated with the
@Injectable decorator
- and implements the
CanActivate interface
- responsible for determining handled by
- a route handler
- or route
-
ere executed
- after every middleware
- but before pips
|----------------| |------------| |-------| |-------| |---------------|
| | | | | | | | | |
| Client Request |---> | Middleware |---> | Guard |---> | Pipes | ---> | Route Handler |
| | | | | | | | | |
|----------------| |------------| |-------| |-------| |---------------|
| ^
| |
|------------------------------|