3

看遍了koa,express以及其衍生框架之后,发现NodeJs的Web开发框架似乎跳不出一个固定的模式,这个问题也困扰着PHP,那就是能不能通过注解来简化开发?
实际上PHP是有“注解”的,不过是通过反射读取注释实现,非常低级。
今天要讲的是一个划时代的NodeJs Web框架——nestjs

示例代码

在介绍nestjs之前,先让大家看一看nestjs的示例代码。

  1. 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 };
  }
}
  1. 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模块架构图

clipboard.png

开始开发

  1. yarn global add @nestjs/cli
  2. nest new projectName
  3. cd projectName && yarn start

写在最后

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


xialeistudio
21.5k 声望5k 粉丝