赞
踩
npm install express-ws
简单逻辑说明:
1.创建连接
2.每个用户都有一个conn 那把conn存入到数组里方便以后广播所接受到的消息,去传达到其他用户
3.对用户数量做一个统计
4.接收到前端传来设置的用户名
代码如下:
在routes文件下新建一个ws.js文件
let express = require("express") const expressWs = require("express-ws") let router = express.Router() expressWs(router) let count = 0 //存放所有连接的用户 let connections = [] router.ws("/", (conn) => { //每个用户都有一个conn count++ console.log(`游客进入聊天室,当前在线人数${count}`) sendMsg(conn, "count", count) //接收用户发来的数据 conn.on("message", function (msg) { let obj = JSON.parse(msg) console.log(obj) if (obj.type === "name") { conn.userName = obj.author connections.push(conn) console.log(`用户的名字为${conn.userName},当前在线人数${count}`) } else if (obj.type === "submit") { broadcast("message", obj) } }) //监听关闭状态 conn.on("close", function () { count-- // broadcast(JSON.stringify({ type: "count", data: count })) broadcast( JSON.stringify({ type: "toast", data: `${conn.userName}离开了聊天室,当前在线人数${count}` }) ) console.log( `用户:${ conn.userName ? conn.userName : "游客" }离开了聊天室,当前在线人数${count}` ) }) }) function broadcast(type, data) { // 群发消息给所有用户 connections.forEach((item) => { item.send(JSON.stringify({ type: type, data: data })) }) } //单独发送给一个用户 function sendMsg(conn, type, data) { conn.send(JSON.stringify({ type: type, data: data })) } module.exports = router
在app.js文件注册路由
var wsRouter = require('./routes/ws');
app.use('/wss', wsRouter);
由于 express-ws 在默认不添加server 参数情况下,使用的是app.listen 创建的httpserver,而express 脚手架将 app和server初始化分离了,所以需要再次配置express-ws
var expressWs = require('express-ws')(app, server);
效果展示
UI用的Ant Design of Vue Comment组件
类似一个实时评论回复的效果
代码展示:
<template> <a-list class="show-box" v-if="comments.length" :data-source="comments" item-layout="horizontal"> <template #renderItem="{ item }"> <a-list-item> <a-comment :author="item.author" :avatar="item.avatar" :content="item.content" :datetime="item.datetime" /> </a-list-item> </template> </a-list> <a-comment> <template #avatar> <a-avatar :src="userInfo?.avatar" /> </template> <template #content> <a-form-item> <a-textarea v-model:value="value" :rows="4" /> </a-form-item> <a-form-item> <a-button html-type="submit" :loading="submitting" type="primary" @click="handleSubmit"> Add Comment </a-button> </a-form-item> </template> </a-comment> </template> <script lang="ts" setup> import { ref, onUnmounted, onMounted } from 'vue'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; dayjs.extend(relativeTime); type Comment = Record<string, string>; const userInfo = JSON.parse(localStorage.getItem('userInfo') as string) // 建立连接 const wsUrl = `ws://${location.host}/socket/wss` const websock = new WebSocket(wsUrl); // 建立连接后发送给后台存用户名 websock.onopen = (evt) => { console.log("Connection open ..."); websock.send(JSON.stringify({ type: 'name', author: userInfo?.nickName, })); }; // 监听后台推送的信息(渲染评论) websock.onmessage = (e) => { const res = JSON.parse(e?.data) console.log(res); if (res.type === 'message') { setTimeout(() => { submitting.value = false; comments.value = [ ...comments.value, res.data, ]; value.value = ''; }, 1000); } } const comments = ref<Comment[]>([]); const submitting = ref<boolean>(false); const value = ref<string>(''); // 提交评论发送后台 const handleSubmit = () => { if (!value.value) { return; } submitting.value = true; const obj = { type: 'submit', author: userInfo?.nickName, avatar: userInfo?.avatar, content: value.value, datetime: dayjs().format('YYYY/MM/DD HH:mm:ss'), } websock.send(JSON.stringify(obj)); }; // 断开连接 onUnmounted(() => { websock.close(); }); </script> <style lang="less" scoped> .show-box { max-height: 520px; overflow: auto; } </style>
代理转发
vite.config.js
server:{
proxy:{
'/api':{
target: "http://localhost:3000", //跨域地址
changeOrigin: true, //支持跨域
rewrite: (path) => path.replace(/^\/api/, "")//重写路径,替换/api
},
'/socket': {
target: 'ws://localhost:3000',
ws: true,
rewrite: (path) => path.replace(/^\/socket/, "")
},
}
}
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。