WebSocket 在express + vue2中的使用

shuke 6月前 105

WebSocket 服务器

express

配置主路由

 /*
 * 2022/11 powered by shuke
 * version 2.0
 * */
 const express = require("express");
 const path = require("path");
 const bodyParser = require("body-parser"); //中间件
 const apiRouter = require("./routes/apiRouter");
 const {jwtAuth} = require("./utils/auth.config");
 const config=require("./config")
 
 //express 实例化
 app = express();
 
 
 app.use(bodyParser.urlencoded({extended: false})); //路由解码
 app.use(bodyParser.json()); //实例使用中间件
 app.use(express.static(path.join(__dirname, config.static))) //功能:用户可直接访问
 
 //跨域(协议,域名,端口号)
 app.all("*", function (req, res, next) {
     //设置允许跨域的域名,*代表允许任意域名跨域
     res.header("Access-Control-Allow-Origin", "*");
     //允许的header类型
     res.header("Access-Control-Allow-Headers", "content-type,Authorization");
     //跨域允许的请求方式
     res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
     //指定本次预检请求的有效期,单位秒,在此期间不用发出另一条预检请求。
     res.setHeader("Access-Control-Max-Age", "3600");
     next();
 });
 
 // 配置CORS跨域资源共享
 // const cors = require('./utils/corsUtil.config.js');
 // app.use(cors);
 
 //token 验证处理err
 app.use(jwtAuth, (err, req, res, next) => {
     try {
         if (err) {
             res.status(401).json({data: err, status: false});
         } else {
             next()
         }
     } catch (e) {
         res.status(401).json({data: e, status: false});
     }
 })
 const expressWS=require("express-ws");
 const wsRouter=require("./routes/wsRouter")
 expressWS(app);
 app.use('/ws', wsRouter);
 
 app.use(config.api, apiRouter)
     .use((req, res) => { //错误重定向 res.redirect(404,"back")
         try {
             res.status(404).json({data: "这个接口没有找到!", status: false});
         } catch (e) {
             res.status(500).json({data: e.message, status: false});
         }
     });
 
     
     app.listen(config.port, config.address, function (err, res) {
         console.log(err?err:"server run http://localhost:"+config.port)
     })

配置子路由

 const express = require("express");
 const WebSocket = require('ws');
 const expressWS = require("express-ws");
 expressWS(express());
 const router = express.Router();
 const M = require("../models/MModel");
 
 function fmtData(msg, type = 1, status = true) {
   return JSON.stringify({
     data: msg,
     type,
     status,
   });
 }
 async function coutTabel() {
   return {
     user: await M.Total("user"),
     cate: await M.Total("cate"),
     movies: await M.Total("movies"),
     cinema: await M.Total("cinema"),
     session: await M.Total("session"),
     order: await M.Total("order"),
   };
 }
 router
   .ws("/root", async function (ws, req) {
     console.log("server启动,已经建立连接。。。");
 
     // 使用 ws 的 send 方法向连接另一端的客户端发送数据
     // ws.send(fmtData('server:欢迎访问服务器'))
     ws.send(fmtData(await coutTabel(), 2));
 
     // 使用 on 方法监听事件
     // message 事件表示从另一段(服务端)传入的数据
     ws.on("message", function (msg) {
       const obj = JSON.parse(msg);
       console.log(`收到信息:`, obj);
       if (obj.num) {
         clearInterval(timer);
         timer = setInterval(async () => {
           ws.send(fmtData(await coutTabel(), 2));
         }, obj.num * 1000);
       }
     });
 
     // 设置定时发送消息
 
     let timer = setInterval(async () => {
       ws.send(fmtData(await coutTabel(), 2));
     }, 10000);
 
     // close 事件表示客户端断开连接时执行的回调函数
     ws.on("close", function (e) {
       console.log("链接关闭");
       clearInterval(timer);
       timer = undefined;
     });
   });
 
   let clients = [];
   let users=[]
   router.ws("/chart", async function (ws, req) {
     clients.push(ws); // 添加新的连接到clients数组
   
     ws.on("message", function (msg) {
       console.log(msg)
       // 当收到消息时,将其广播到所有连接的客户端
       clients.forEach(client => {
         console.log(client !== ws,client.readyState === WebSocket.OPEN);
         if (client !== ws && client.readyState === WebSocket.OPEN) {
         
           client.send(fmtData({data: msg}, 2));
         }
       });
     });
   
     ws.on("close", function (e) {
       console.log("链接关闭");
       // 移除关闭的连接
       clients = clients.filter(client => client !== ws);
       ws.send(fmtData({ data: "链接关闭" }, 1));
     });
   });
 
 module.exports = router;
 

客户端  自动更新

/ws/root

混入

 import {Message} from "element-ui"
 
 export default {
     data() {
         return {
             interval:10,
             list: null,
             ws: null,
             updateNum:0
         }
     },
     computed: {
         wsOpen(){
             return Boolean(this.ws)
         }
     },
     methods: {
         connect() {
             if (this.ws) {
                 this.closeConnect();
             }
 
             this.ws = new WebSocket("ws://127.0.0.1:5500/ws/root");
             const {ws} = this;
 
             ws.onopen = () => {
                 console.log("连接成功", ws);
                 Message.success("WebSocket连接成功")
             };
 
             ws.onmessage = (evt) => {
                 console.log("Message received: ", evt.data);
                 const res = JSON.parse(evt.data)
                 if (res.type == 2) {
                     this.updateNum++;
                     if(JSON.stringify(res.data)!=JSON.stringify(this.list)){
                         this.list = res.data;
                     }
 
                 }
             };
 
             ws.onclose = () => {
                 console.log("完成关闭");
                 Message.info("WebSocket完成关闭")
                 this.ws = null;
                 this.updateNum=0;
             };
         },
         sendMessage() {
             const {ws} = this;
             if (ws && ws.readyState === WebSocket.OPEN) {
                 ws.send(JSON.stringify({num:this.interval}));
             } else {
                // console.log("Not connected or connection is closing or closed");
                 Message.error("服务器连接失败")
             }
         },
         closeConnect() {
             this.ws.close();
         }
     },
     beforeUnmount() {
         this.closeConnect()
     }
 
 
 }

组件

 <template>
     <el-card class="margin">
         <div slot="header">
             <div class="float-right">
                 <el-switch
                         :value="wsOpen"
                         active-color="#13ce66"
                         inactive-color="#ff4949">
                 </el-switch>
             </div>
             <span>WebSocket 案例</span>
 
         </div>
         <el-button-group>
             <el-button type="success"
                        :loading="wsOpen"
                        @click="connect">{{ws?'更新'+updateNum:'连接'}}</el-button>
         </el-button-group>
         <el-button-group v-show="wsOpen" class="float-right">
             <el-button type="danger"  @click="closeConnect">断开</el-button>
             <el-input-number v-model="interval" :min="1" :max="100"></el-input-number>
             <el-button type="primary" @click="sendMessage">设置</el-button>
         </el-button-group>
 
 
         <el-row class="text-center" v-if="list">
             <el-col v-for="(value,key) in list" :key="key" :span="8">
                 <el-card class="margin">
                     <h1>{{value}}</h1>
                     <h3>{{key}}</h3>
                 </el-card>
             </el-col>
         </el-row>
     </el-card>
 </template>
 
 <script>
     import ws from "../mixins/ws.js"
     export default {
         name: "wsCom",
         components: {}, //加载子组件
         mixins: [ws],
     }
 </script>

客户端 聊天室

/ws/chart

混入

 import {Message} from "element-ui"
 
 export default {
     data() {
         return {
             msg:"hello "+new Date(),
             list:[],
             user:{name:""},
             ws: null,
         }
     },
     computed: {
         wsOpen(){
             return Boolean(this.ws)
         }
     },
     methods: {
         connect() {
             if (this.ws) {
                 this.closeConnect();
             }
 
             this.ws = new WebSocket("ws://127.0.0.1:5500/ws/chart");
             const {ws} = this;
 
             ws.onopen = () => {
                 console.log("连接成功", ws);
                 Message.success("WebSocket连接成功")
             };
 
             ws.onmessage = (evt) => {
                 console.log("Message received: ", evt.data);
                 const res = JSON.parse(evt.data)
                 if (res.type == 2) {
 
                         this.list = [...this.list,JSON.parse(res.data.data)];
 
                     this.$nextTick(()=>{
 
                         //this.$refs.box.scrollTop=this.$refs.box.scrollHeight
                     })
 
                 }
                 console.log(this.$refs.box)
             };
 
             ws.onclose = () => {
                 console.log("完成关闭");
                 Message.info("WebSocket完成关闭")
                 this.ws = null;
                 this.list=[]
             };
         },
         sendMessage() {
             if (!this.msg){return}
             const {ws} = this;
             if (ws && ws.readyState === WebSocket.OPEN) {
                 const obj={msg:this.msg,user:{...this.user},date:+new Date()}
                 this.list = [...this.list,obj];
                 ws.send(JSON.stringify(obj));
             } else {
                 Message.error("服务器连接失败")
             }
         },
         closeConnect() {
             this.ws.close();
         }
     },
     beforeUnmount() {
         this.closeConnect()
     }
 
 
 }

组件

 <template>
     <el-card class="margin">
         <div slot="header">
             <div class="float-right">
                 <el-button size="mini" type="success" @click="list=[]">清空</el-button>
                 <el-button size="mini" type="danger" @click="closeConnect" v-if="wsOpen">退出</el-button>
             </div>
             <span>在线聊天室  <strong>{{user.name}}</strong></span>
             <el-switch :value="wsOpen"></el-switch>
 
         </div>
         <div class="padding-y">
 
             <el-input v-model="user.name" v-if="!ws">
 
                 <el-button slot="append" @click="connect" :loading="!Boolean(user.name)"> 加入</el-button>
             </el-input>
         </div>
 
         <div  >
 
             <ul v-if="list.length" style="max-height: 400px;padding:0 2em;overflow: auto" ref="box" id="box">
                 <li v-for="(item,index) in list" :key="index" class="padding-y ">
                     <div :class="user.name==item.user.name?'text-right':''">
                         <el-badge :value="index+1" type="primary">
                             <el-button size="small">
                                 {{item.user.name}} -
                                 {{item.date|setDateTime}}
                             </el-button>
                         </el-badge>
                     </div>
                     <el-alert :closable="false" :title="item.msg"></el-alert>
                 </li>
             </ul>
         </div>
         <div class="" v-if="wsOpen"  >
             <el-input v-model="msg">
                 <el-button slot="append" @click="sendMessage"> 发送</el-button>
             </el-input>
         </div>
     </el-card>
 </template>
 
 <script>
     import chat from "../mixins/chat.js"
 
     export default {
         name: "chartCom",
         components: {},
         mixins: [chat],
         data() {
             return {}
         },
 
     }
 </script>



上传的附件:
最新回复 (0)
全部楼主
返回