看遍了koa,express以及其衍生框架之后,发现NodeJs的Web开发框架似乎跳不出一个固定的模式,这个问题也困扰着PHP,那就是能不能通过注解来简化开发?
实际上PHP是有“注解”的,不过是通过反射读取注释实现,非常低级。今天要讲的是一个划时代的NodeJs Web框架——示例代码
在介绍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, OnGatewayConnection { 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 { 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的详细文档可以前往官网查看,本文只是做个框架介绍,开启新世界的大门。