乐趣区

NestJs简明教程

看遍了 koa,express 以及其衍生框架之后,发现 NodeJs 的 Web 开发框架似乎跳不出一个固定的模式,这个问题也困扰着 PHP,那就是能不能通过注解来简化开发?实际上 PHP 是有“注解”的,不过是通过反射读取注释实现,非常低级。今天要讲的是一个划时代的 NodeJs Web 框架——nestjs
示例代码
在介绍 nestjs 之前,先让大家看一看 nestjs 的示例代码。
HTTP 接口
@Controller(‘socket’)
@UseGuards(AdminGuard)
export class SocketController {
private logger: Logger = new Logger(SocketController.name);

constructor(private readonly gateway: SocketGateway,
private readonly salesmanService: SalesmanService,
private readonly hashidService: HashidService) {
}

@Post(‘interaction’)
async send(@Query(‘salesman_id’) salesmanId: number, @Query(‘user_id’) userId: number, @Body(‘content’) content: string) {
if (!salesmanId || !userId || !content) {
throw new BadRequestException(‘Bad Request’);
}
const salesman = await this.salesmanService.findById(salesmanId);
if (!salesman) {
throw new NotFoundException(‘ 销售不存在 ’);
}
const roomId = this.salesmanService.makeSyncRoomKey(salesman);
this.gateway.namespace.to(roomId).emit(SocketEvent.OnInteraction, { user_id: this.hashidService.encode(userId), content });
return {errmsg: ‘ok’, errcode: 0};
}
}
Socket.IO
@UseFilters(new WsExceptionFilter())
@WebSocketGateway({namespace: ‘socket’, adapter: adapter(appConfig.redis) })
export class SocketGateway implements OnGatewayInit<SocketIO.Namespace>, OnGatewayConnection<SocketIO.Socket> {
private logger: Logger = new Logger(SocketGateway.name);
@WebSocketServer() public readonly namespace: SocketIO.Namespace;
public adapter: adapter.RedisAdapter;

constructor(
private readonly salesmanService: SalesmanService,
private readonly corporationService: CorporationService,
private readonly hashidService: HashidService,
private readonly userService: UserService,
private readonly roomService: RoomService,
private readonly messageService: MessageService,
private readonly readService: ReadService,
private readonly memberService: MemberService,
) {
}

afterInit(server: SocketIO.Namespace): any {
this.adapter = server.adapter as adapter.RedisAdapter;
this.logger.log(`initialized ${server.name}`);
}

/**
* 进入聊天室
* @param {SocketIO.Socket} client
* @returns {any}
*/
async handleConnection(client: SocketIO.Socket): Promise<any> {
const {user_id, token, corporation_id, sign} = qs.parse(url.parse(client.request.url).query) as {
[name: string]: string;
};
if (!user_id && !token && !corporation_id && !sign) {
client.disconnect(true);
return;
}
const realUserId = this.hashidService.decode(user_id);
await promisify(client.join.bind(client))(this.roomService.makePersonalRoomId(realUserId)),
client.emit(SocketEvent.Ready);
}

@SubscribeMessage(SocketEvent.Join)
handleJoin(client: SocketIO.Socket, data: any) {
if (JoinType.Chat === data.type) {
return this.handleJoinChat(client, data);
}
if (JoinType.Sync === data.type) {
return this.handleJoinSync(client, data);
}
client.disconnect(true);
}

@SubscribeMessage(SocketEvent.Leave)
async handleLeave(client: SocketIO.Socket, data: any) {
const {user_id, token, corporation_id, sign} = qs.parse(url.parse(client.request.url).query) as {
[name: string]: string;
};
if (JoinType.Chat === data.type) {
await promisify(client.leave.bind(client))(data.room_id);
return {event: SocketEvent.Leave, data};
}
const isPersonal = user_id && token;
const roomId = isPersonal
? await this.salesmanService.getRoomId(user_id, token)
: await this.corporationService.getRoomId(corporation_id, sign);
if (roomId) {
await promisify(client.leave).bind(client)(roomId);
}
return {event: SocketEvent.Leave, data};
}
// …
写法是不是很像 Java? 或者说是 Angular4?
介绍
实际上 nestjs 的架构源自于 java 的 spring 框架,而代码组织则借鉴与 Angular4 的 Module。
nestjs 模块架构图

开始开发

yarn global add @nestjs/cli
nest new projectName
cd projectName && yarn start

写在最后
由于篇幅关系,nestjs 的详细文档可以前往官网查看,本文只是做个框架介绍,开启新世界的大门。

退出移动版