- A+
所属分类:Web前端
ExpressJS
集成WebSocket
1.版本
"express": "~4.16.1", "express-ws": "^5.0.2",
2.简单使用
app.js
const express = require('express'); const app = express(); const expressWs = require('express-ws')(app) //混入app app.ws('/ws',(ws,req)=>{ ws.on('message',msg=>{ console.log(msg) ws.send(msg) }) }) app.listen('3000')
局部路由
//websocket.js const express = require('express'); const router = express.Router(); router.ws('/router-ws',(ws,req)=>{ ws.on('message',msg=>{ console.log(msg) ws.send(msg) }) }) module.exports = router
app.js完整代码
const express = require('express'); const app = express(); const expressWs = require('express-ws')(app) //混入app app.ws('/ws',(ws,req)=>{ ws.on('message',msg=>{ console.log(msg) ws.send(msg) }) }) var webSocket = require('./websocket.js') app.use(webSocket) app.listen('3000')
3.封装express-ws
将 “express-ws” 封装,通过 express 的 router 模块化
websocket.js
// 引入 const express = require('express'); const router = express.Router(); const expressWs = require('express-ws')
封装通道类
1.创建通道类 channel,引入router定义websocket连接组,调用时传入路径 path 进行区分
//类 class channel { router; constructor(props) { this.router = props; } createChannel(path) { // 建立通道 this.router.ws('/' + path, (ws, req) => { ws.on('message', (msg) =>{ console.log(msg) }) }) } }
调用方法
let channels = new channel(router) //创建一个新的通道 路径为:/ws channels.createChannel('ws') //访问路径: ws://localhost:3000/ws
2.监听websocket实例,在外部函数监听实例返回参数,并通过 path 区分
//类 class channel { router; constructor(props) { this.router = props; } createChannel(path) { // 建立通道 this.router.ws('/' + path, (ws, req) => { ws.on('message', (msg) => getMsg(msg, path)) }) } } //外部函数监听客户端消息 let getMsg = (msg, from) => { switch (from) { case 'ws': console.log('ws:', msg); break; } }
3.根据路由分类存储已连接用户,添加 saveClients() 方法
//类 class channel { router; clients = { allClients: [],//存放通过当前类所创建的通道中所有已连接用户 }; constructor(props) { this.router = props; } createChannel(path) { this.clients[path] = []; //用于存放当前通道中的用户 // 建立通道 this.router.ws('/' + path, (ws, req) => { // 保存用户 this.saveClients(ws, req, path) ws.on('message', (msg) => getMsg(msg, path)) }) } // 保存用户 saveClients(socket, req, path) { let client = { id: req.query.id, socket, } this.clients.allClients.push(client) this.clients[path].push(client) } } // 外部函数监听客户端消息 let getMsg = (msg, from) => { switch (from) { case 'ws': console.log('ws:', msg); break; } }
入口函数 initWebSocket
编写入口函数,通过入口函数引入app,操作 express-ws。将 .ws 方法混入app内
调用封装的channel类,去创建通道
//初始化 let WS = null; // 声明一个通道类 let channels = null; function initWebSocket(app) { WS = expressWs(app) //混入app, wsServer 存储所有已连接实例 // 创建通道 channels = new channel(router) channels.createChannel('ws') //访问路径: ws://localhost:3000/ws app.use(router) }
完整代码:
//websocket.js const express = require('express'); const router = express.Router(); const expressWs = require('express-ws') // 初始化 let WS = null; // 声明一个通道类 let channels = null; function initWebSocket(app) { WS = expressWs(app) //混入app, wsServer 存储所有已连接实例 // 创建通道 channels = new channel(router) channels.createChannel('ws') channels.createChannel('ws2') app.use(router) } // 通道类 class channel { router; clients = { allClients: [],//存放通过当前类所创建的通道中所有已连接用户 }; constructor(props) { this.router = props; } createChannel(path) { this.clients[path] = []; //用于存放当前通道中的用户 // 建立通道 this.router.ws('/' + path, (ws, req) => { // 保存用户 this.saveClients(ws, req, path) ws.on('message', (msg) => getMsg(msg, path)) ws.on('close', (code) => close(code, path)) ws.on('error', (e) => error(e, path)) }) } // 保存用户 saveClients(socket, req, path) { let client = { id: req.query.id, socket, } this.clients.allClients.push(client) this.clients[path].push(client) } } /** * * @param {*} msg 消息内容 * @param {String} from 消息来源 */ // 监听消息 let getMsg = (msg, from) => { switch (from) { case 'ws': console.log('ws:', msg); break; case 'wsw': console.log('wsw:', msg); break; } SendMsgAll({ data: msg }) } // 发送消息 let sendMsg = (client, data) => { if (!client) return client.send(JSON.stringify(data)) } let close = (code) => { console.log('关闭连接', code); } let error = (e) => { console.log('error: ', e); } // 群发 /** * * @param {String} path 需要发送的用户来源 路由,默认全部 * @param {*} data 发送的数据 */ function SendMsgAll({ path = '/', data = "" }) { let allClientsList = Array.from(WS.getWss(path).clients) for (let key in allClientsList) { let client = allClientsList[key] if (client._readyState == 1) { sendMsg(client, data) } } } module.exports = { initWebSocket, SendMsgAll }
app.js 挂载
const express = require('express'); const app = express(); // WebSocket 在JWT验证之前引入挂载 const webSocket = require('./websocket') webSocket.initWebSocket(app) app.listen('3000')
初步整理,功能不够全面,后续会进一步更新,欢迎评论区互相交流~