nodejs编写ws服务是非常简单高效的,nodejs有众多的实现ws的库,如ws,SocketIO等,nodejs的事件线程是单线程的,所以不要在事件线程内做阻塞性的操作,耗时的操作交给工作线程或者子进程操作。
我使用nodejs+vue3实现了写了个简单的聊天室demo
1.nodejs服务端代码
node init初始化项目
安装ts
具体可以看我nodejs 使用ts的文章
安装ws的库
npm install ws
npm install @types/ws
import {WebSocketServer,WebSocket} from 'ws';
const wss = new WebSocketServer( {port:3000});
wss.on('connection',(ws)=>{
console.info('new connection join',ws);
ws.on('message',(data)=>{
wss.clients.forEach((client=>{
if (client.readyState === WebSocket.OPEN) {
client.send(data,{binary:false});
}
}))
console.info('get msg from client',(new String(data)).toString());
})
});
console.log('start success');
2. vue3连接客户端
使用游览器自带的WebSocket对象连接ws服务,使用ws库的WebSocket对象在游览器运行时会报错,存在一定的问题,
<script setup lang="ts">
import { onMounted, ref } from "vue"
import { Msg } from "@/model"
const props=defineProps<{
username: string
}>();
const toSendMsg = ref("");
const username=props.username;
const receiveMsgList = ref<Msg[]>([])
const ws = new WebSocket('ws://localhost:3000');
onMounted(() => {
// WebSocket 服务器的 URL
const wsUrl = 'ws://localhost:3000';
// 创建 WebSocket 连接
const ws = new WebSocket(wsUrl);
// 监听连接成功事件
ws.addEventListener('open', function () {
console.log('Connected to WebSocket server');
// 发送消息给服务器
});
// 监听接收到消息事件
ws.addEventListener('message', function (event) {
console.log('Blob content as string:', event.data);
receiveMsgList.value.push(JSON.parse(event.data))
});
// 监听连接关闭事件
ws.addEventListener('close', function () {
console.log('Disconnected from WebSocket server');
});
// 监听连接错误事件
ws.addEventListener('error', function (error) {
console.error('WebSocket error:', error);
});
})
function sendMsg(){
const msgInfo= new Msg(username,toSendMsg.value)
ws.send(JSON.stringify(msgInfo));
toSendMsg.value="";
}
</script>
<template>
<el-col :span="6">
<div class="chart-out-box">
<div class="chart-room-head">
<el-scrollbar height="400px">
<div v-for="(item, index) in receiveMsgList" :key="index">
<p v-if="item.username == username" class="scrollbar-demo-item scrollbar-demo-is-own">
{{item.content}}<span>{{ ":"+username }}</span>
</p>
<p v-else class="scrollbar-demo-item scrollbar-demo-is-other">
<span>{{item.username}}:</span>{{ item.content }}</p>
</div>
</el-scrollbar>
</div>
<div class="chart-room-footer">
<el-input v-model="toSendMsg" style="width: 240px" :rows="4" type="textarea" placeholder="Please input" />
<el-button type="success" style="margin-left:20px" @click="sendMsg">发送</el-button>
</div>
</div>
</el-col>
</template>
<style lang="scss" scoped>
.chart-out-box {
border: 1px solid blue;
height: 400px;
}
.chart-room-head {
height: 70%;
border: 1px solid green;
;
}
.chart-room-footer {}
.scrollbar-demo-item {
display: flex;
align-items: center;
height: 50px;
margin: 10px;
text-align: center;
border-radius: 4px;
background: var(--el-color-primary-light-9);
color: var(--el-color-primary);
}
.scrollbar-demo-is-own {
justify-content: right;
}
.scrollbar-demo-is-other {
justify-content: left;
}
</style>
3.演示
4.git代码
https://github.com/haozhi-ly/chatroom-demo