ExpressJS使用express-ws的实例详解

 更新时间:2023年09月02日 12:06:21   作者:Erick-K  
这篇文章主要介绍了ExpressJS使用express-ws的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

版本

"express": "~4.16.1",
"express-ws": "^5.0.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')

封装express-ws

将 “express-ws” 封装,通过 express 的 router 模块化

websocket.js

// 引入
const express = require('express');
const router = express.Router();
const expressWs = require('express-ws')

封装通道类

  • 创建通道类 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
  • 监听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;
    }
}
  • 根据路由分类存储已连接用户,添加 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

//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')

源码

Gitee源码仓库地址:源码

到此这篇关于ExpressJS使用express-ws的文章就介绍到这了,更多相关ExpressJS使用express-ws内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 微信小程序实现一键登录

    微信小程序实现一键登录

    这篇文章主要为大家详细介绍了微信小程序实现一键登录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • JS中如何优雅的使用async await详解

    JS中如何优雅的使用async await详解

    async表示异步,而await可以看作async wait,个人对async与await的简单理解就是,我们可以用同步的方式去书写异步代码,这篇文章主要给大家介绍了关于JS中如何优雅的使用async await的相关资料,需要的朋友可以参考下
    2021-10-10
  • js字符串操作方法实例分析

    js字符串操作方法实例分析

    这篇文章主要介绍了js字符串操作方法,实例分析了javascript中slice、substr及substring等方法的使用技巧,需要的朋友可以参考下
    2015-05-05
  • JavaScript中自定义事件用法分析

    JavaScript中自定义事件用法分析

    这篇文章主要介绍了JavaScript中自定义事件用法,较为详细的分析了自定义事件的原理与具体用法,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • es6 super关键字的理解与应用实例分析

    es6 super关键字的理解与应用实例分析

    这篇文章主要介绍了es6 super关键字的理解与应用,结合实例形式分析了es6 super关键字的功能、原理、用法及相关操作注意事项,需要的朋友可以参考下
    2020-02-02
  • avalon js实现仿google plus图片多张拖动排序附源码下载

    avalon js实现仿google plus图片多张拖动排序附源码下载

    这篇文章主要介绍了avalon js实现仿google plus图片多张拖动排序附源码下载的相关资料,需要的朋友可以参考下
    2015-09-09
  • 五句话帮你轻松搞定js原型链

    五句话帮你轻松搞定js原型链

    这篇文章主要给大家介绍了关于js原型链的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 五段实用的js高级技巧

    五段实用的js高级技巧

    五段实用的js高级技巧,一些不错的小技巧,学习js的朋友可以看看。
    2011-12-12
  • 微信小程序嵌入腾讯视频源过程详解

    微信小程序嵌入腾讯视频源过程详解

    这篇文章主要介绍了微信小程序嵌入腾讯视频源过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • Layui给switch添加响应事件的例子

    Layui给switch添加响应事件的例子

    今天小编就为大家分享一篇Layui给switch添加响应事件的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09

最新评论