放弃云数据库!基于NestJS的WebSocket实时通信方案实践

背景

在开发3D骰子联机小程序时,多人游戏功能需要实时同步房间的操作状态(如房主开盅动作)。初期采用小程序云开发数据库的watch监听机制实现状态同步,虽能完成基础功能,但存在致命体验短板------云函数响应延迟高达1-2秒,与骰子游戏强实时的特性产生明显冲突。

于是为追求更丝滑的实时交互的用户体验,决定选择通过 WebSocket 重构通信层,下文将详解一下通过 nest 实现与小程序实时通信的方案。

实现

首先我们通过 nest 的脚手架来初始化一下项目

arduino 复制代码
nest new websocket-demo

运行一下项目,启动成功

接着我们安装对应的所需的websocket的依赖

css 复制代码
npm i --save @nestjs/websockets @nestjs/platform-ws ws

最开始用的 socket.io 依赖实现,结果后面发现小程序不支持 socket.io ,需要下载一些兼容库来结合使用,于是就换了方案。

接下来我们需要为应用注入 WebSocket 适配器,在main.ts中配置一下 主要作用

  • 将传统的 HTTP 服务扩展为 同时支持 HTTP + WebSocket 双协议
  • 通过适配器模式,让 WebSocket 的底层实现(如 wssocket.io 库)与框架的路由、中间件等系统无缝对接。
js 复制代码
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { WsAdapter } from '@nestjs/platform-ws';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useWebSocketAdapter(new WsAdapter(app));
  await app.listen(3000);
}
bootstrap();

接下来需要配置一下 WebSocket 网关

js 复制代码
import { SubscribeMessage, WebSocketGateway, WebSocketServer, OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
import { Server, WebSocket } from 'ws';

@WebSocketGateway(3001) // 指定ws端口号,不配置则默认与http服务相同端口
export class WsGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;

  // 初始化后执行
  afterInit(server: Server) {
    console.log('WebSocket server initialized');
  }

  // 处理新连接
  handleConnection(client: WebSocket, ...args: any[]) {
    console.log('Client connected:');
  }

  // 处理断开连接
  handleDisconnect(client: WebSocket) {
    console.log(`Client disconnected: ${client}`);
  }

  // 消息处理示例
  @SubscribeMessage('message') // 这里的message对应的是前端发送ws请求的里的event值
  handleMessage(client: WebSocket, payload: any): string {
    console.log('handleMessage message:', payload);
    client.send(JSON.stringify({ event: 'message', data: `我收到了你发的消息${payload}` })); // 回发消息
    return 'OK';
  }
}

还需要在 app.module.ts 中引入 socket 网关

js 复制代码
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { WsGateway } from './ws.gateway';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService, WsGateway], // 这里
})
export class AppModule {}

我们重新跑一下后端服务

然后在小程序中的app.vue中的 onLaunch 写连接本地 WebSocket 服务的代码

js 复制代码
const conSocket = wx.connectSocket({
  url: 'ws://localhost:3001',
  success: () => console.log('Connecting...'),
})

// 监听事件
conSocket.onOpen(() => {
  console.log('Connected!');
});

conSocket.onMessage((res: any) => {
  const { data } = res
  console.log('onMessage-msg', data);
});

conSocket.onError((err) => {
  console.error('Error:', err);
});

conSocket.onClose(() => {
  console.log('Connection closed');
});

小程序项目运行起来

发现连接成功了!!!

接下来我来试一下双向通信,在连接打开的时候,我们给服务端发送点内容

js 复制代码
conSocket.onOpen(() => {
    console.log('Connected!');
    conSocket.send({
      data: JSON.stringify({
        event: 'message',
        data: {
          msg: 'Hello, server!'
        }
      }),
      success: () => console.log('Message sent')
    })
  });

可以看到服务器与小程序之间的双向通信没问题,并且响应很快,非常符合我们的联机功能。

✨ 总结

  • 旧方案:云数据库watch监听

    • 延迟1-2秒,体验割裂
    • 被动轮询,资源消耗大
  • 新方案:NestJS+WebSocket

    • 延迟<100ms,毫秒级响应
    • 主动推送,节省资源

对于前端来说,用户体验极其重要,我自己在开发过程中,都会让自己从用户的角度,来体验流程,这也有助于自己去思考,去进行一些性能优化。

相关推荐
源码_V_saaskw9 天前
宇鹿家政服务系统小程序ThinkPHP+UniApp
微信小程序·小程序·uni-app·微信公众平台
掉头发的王富贵10 天前
如何用WebSocket完成实时消息,实时进度条
websocket·网络协议·http
2501_9159214310 天前
后台发热、掉电严重?iOS 应用性能问题实战分析全过程
websocket·网络协议·tcp/ip·http·网络安全·https·udp
小鸡脚来咯10 天前
WebSocket快速入门
网络·websocket·网络协议
即可皕10 天前
WebSocket长连接在小程序中的实践:消息推送与断线重连机制设计
websocket·网络协议·小程序
Q_Q196328847510 天前
python基于微信小程序的广西文化传承系统
开发语言·spring boot·python·微信小程序·django·flask
00后程序员张10 天前
用Fiddler抓包工具优化API联调流程:与Postman、Wireshark协作实践分享
websocket·网络协议·tcp/ip·http·网络安全·https·udp
kingbal10 天前
uniapp:微信小程序胶囊「复制链接」灰色处理
微信小程序·小程序·uni-app
知否技术10 天前
2025微信小程序开发实战教程(四)
前端·微信小程序
2501_9240641110 天前
微信小程序自动化测试方案实践过程 2025最新实践白皮书
微信小程序·小程序