NestJS小技巧21-在NestJS中创建您的第一个基于WebSockets的应用程序
什么是Websockets
Websockets是一种通信协议,通过在web浏览器和web服务器之间建立的单个TCP连接提供全双工通信信道。这允许服务器在不被客户端调用的情况下发送到浏览器。Websockets有很多用途,比如聊天应用程序或帐户余额,…所有内容都需要实时更新
Next JS中的Websockets
根据NestJS的说法,网关只是一个用@WebSocketGateway()
decorator注释的类。从技术上讲,网关与平台无关,这使得它们在创建适配器后与任何WebSockets库都兼容。
设置
我准备构建一个简单的发送和接收消息的应用
首先,我们需要安装这些依赖
pnpm i socket.io @nestjs/websockets @nestjs/platform-socket.io
接着,我们创建Gateway叫MessageGateway
export class MessageGateway
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
}
不要忘了在MesssageModule
里添加providers
@Module({
imports: [TypeOrmModule.forFeature([Message])],
controllers: [MessagesController],
providers: [MessagesService, MessageGateway],
})
export class MessagesModule {}
创建服务
现在IDE会提示您,您需要在MessageGteway
实现afterInit``handleDisconnect``handleConnecion
这些方法。
因为这是一个简单的app应用,所以我们并不需要真的在这些方法里面做什么,因此我将会检点的log一些数据
private logger: Logger = new Logger('MessageGateway');
@WebSocketServer() wss: Server;
afterInit(server: Server) {
this.logger.log('Initialized');
}
handleDisconnect(client: Socket) {
this.logger.log(`Client Disconnected: ${client.id}`);
}
handleConnection(client: Socket, ...args: any[]) {
this.logger.log(`Client Connected: ${client.id}`);
}
有了这些,我们将知道服务什么时候启动,哪个客户端连接或者断开连接。
处理事件
在这个应用里我们需要2个事件,第一个是sendMessage
,第二个是receiveMessage
@SubscribeMessage('sendMessage')
async handleSendMessage(client: Socket, payload: string): Promise<void> {
const newMessage = await this.messagesService.createMessage(payload);
this.wss.emit('receiveMessage', newMessage);
}
在这段代码中,我将会使用SubscribeMessage
来装饰订阅的sendMessage
事件。不管什么时候sendMessage
事件被触发,将会通过messageService
创建一个新的消息。
然后我们将会通过receiveMessage
事件来发送这条被创建的消息。
创建客户端
为了测试gateway,我们需要一个客户端,我将使用Vue3
来测试。
因为服务使用了socket.io
,我们需要安装socket.io
。
pnpm i socket.io-client
接下来,我们用它来创建一个socket
import io from "socket.io-client";
const socket = io("http://localhost:3000");
接着,实现这个socket的连接
// socket.ts
import { reactive } from "vue";
import { io } from "socket.io-client";
export const state = reactive({
connected: false,
fooEvents: [],
barEvents: [],
});
const URL: string = "http://localhost:3000";
export const socket = io(URL);
socket.on("connect", () => {
state.connected = true;
});
socket.on("disconnect", () => {
state.connected = false;
});
// App.tsx
import { socket } from "./socket";
const App = defineComponent({
name: "App",
setup() {
const state = reactive<{
value: string;
list: string[];
}>({
value: "",
list: [],
});
// 页面渲染前让socket创建连接
onBeforeMount(() => {
socket.connect();
});
// 页面加载完成后,监听receiveMessage事件
onMounted(() => {
socket.on("receiveMessage", (e: any) => {
state.list.push(e.content);
});
});
// 页面消除时断开连接
onUnmounted(() => {
socket.disconnect();
});
// 点击按钮发送socket消息
const handleClick = () => {
socket.timeout(5000).emit("sendMessage", state.value, (e: any) => {
console.log(e);
});
};
return () => {
return (
<div>
<input v-model={state.value} />
<button onClick={handleClick}>send message</button>
<div>
<ul>
{state.list.map((item) => (
<li>{item}</li>
))}
</ul>
</div>
</div>
);
};
},
});
export default App;
您可以看到,在第一次渲染时,我将订阅receiveMessage
事件,以侦听是否有任何新事件,并使用receiveMessage
方法执行操作。
在receiveMessage
方法中,我在state中添加了新的消息
每次我发送一条新的消息,我会发送sendMessage
事件
它的结果将是
总结
转载自:https://juejin.cn/post/7243828459288969275