效果动态图
我们使用WebSocket写一个这样的小demo:
- 演示网址:http://ashuai.work:8888/#/WebSocket (点击跳转观看效果)
- 前端代码仓库地址:https://github.com/shuirongshuifu/elementSrcCodeStudy
- 后端代码仓库地址:https://github.com/shuirongshuifu/express-ws-server
WebSocket相关知识复习
什么是WebSocket,解决了什么问题
- WebSocket是html5推出的新特性,新功能,是一种新的网络通讯协议
- WebSocket解决了http只能单向请求的缺陷(http只能由客户端向服务端发请求)
- 使用WebSocket协议可以做到,客户端和服务端相互发送消息
- http和WebSocket二者长相区别:
http://ashuai.work:6789/url
和ws://ashuai.work:6789/url
(就最前面的协议变了)
WebSocket应用场景
对于实时性要求比较高的功能需求,如:
- 聊天室功能
- 实时股票行情功能
- 体育竞赛直播功能
- 最新天气
- 最新消息(订阅发布,小红点未读消息)
- 多人协同编辑文档(及时更新)
- 监控功能(监控位置、监控相关数据搭配可视化图表)
- 在线客服
基本WebSocket的八股文概念没啥意思,大家可移步到MDN官方文档瞅瞅
这里我们通过一个例子去学习,一目了然哎
举个WebSocket实际例子
例子需求
- 可创建WebSocket服务,并关闭之
- 实现客户端可以向服务端发送请求
- 实现服务端可以向客户端推送消息
- 存储后端推送的每一条消息
- 类编程,便于前端多个地方复用
- ......
后端用express-ws开启WebSocket服务
这里我们使用npm上的一个比较优秀的包:express-ws
,地址如下:https://www.npmjs.com/package/express-ws/v/5.0.2
当然,前提是我们需要搭建一个express环境,这里我们不赘述,直接上代码:
代码中,已经有相关注释啦...
app.js文件中使用express-ws包注入.ws接口方法
const express = require('express') // 引入express插件包并生成一个实例app
const app = express()
// 引入express-ws的WebSocket功能,并混入app,相当于为 app实例添加 .ws 方法
const expressWs = require('express-ws')(app)
const Router = require('./router') // 引入分模块管理的路由
app.use(Router) // 路由分模块
app.listen(10000, (req,res) => { // 在10000端口上启动后端服务
console.log('后端服务端口地址为: http://localhost:10000');
})
router.js中使用route.ws创建WebSocket接口服务
/**
* route.ws('/url',(ws, req)=>{ })
* 建立WebSocket服务,并指定对应接口url,及相应回调
* ws为实例化的对象,req即为请求
*
* ws.send方法用来向客户端发送信息
* ws.on方法用于监听事件(如监听message事件,或监听close事件)
* */
route.ws('/mySocketUrl', (ws, req) => {
// console.log('连接成功', ws)
ws.send('来自服务端推送的消息')
ws.on('message', function (msg) {
ws.send(`收到客户端的消息为:${msg},再返回去`)
})
// 使用定时器不停的向客户端推动消息
let timer = setInterval(() => {
ws.send(`服务端定时推送消息: ${getNowTime()}`)
}, 1000)
ws.on('close', function (e) {
// console.log('连接关闭')
clearInterval(timer)
timer = null
})
})
有的道友说,这样看着也不方便,有没有完整的后端代码啊,我想运行起来,更加直观,方便,那必须有哎
就在,笔者的GitHub仓库里呢,地址:https://github.com/shuirongshuifu/express-ws-server
欢迎各位道友 御键飞行,云游
笔者的仓库
前端使用class类编程,方便复用WebSocket功能
在写代码之前,我们要分析一下功能,以便于设计class类
- 首先,既然是WebSocket,那肯定要指定后端的服务地址在哪里,所以要有url这个参数
- 另外因为我们使用的是WebSocket构造函数,是要实例化出来的,所以需要再定义一个变量socket用于存储实例化好的WebSocket对象
- 既然还要存储后端推送的每一条消息,那就干脆定义一个数组messageArr吧
于是乎,我们就可以这样写:
class myWebSocket {
constructor(url) {
this.url = url || 'ws://ashuai.work:10000/mySocketUrl' // 指定默认ws的地址
this.socket = null // 实例化的ws对象
this.messageArr = [] // 接收服务端推送的消息数组
}
}
constructor可以用来接收参数,就像函数接收参数一样
- 接下来,还需要创建(开启)一个WebSocket服务
- 以及这个WebSocket服务需要能够发送消息
- 当然了,能创建(开启),也要能关闭
于是乎我们在myWebSocket这个类中添加三个方法,分别是创建createFn
、发送sendFn
、关闭closeFn
class myWebSocket {
constructor(url) { ...... }
createFn() {
this.socket = new WebSocket(this.url) // 生成WebSocket实例化对象
// 使用WebSocket的原生方法onopen去连接开启
this.socket.onopen = function (e) {
console.log('连接成功')
}
// 使用WebSocket的原生方法onerror去兜错一下
this.socket.onerror = (e) => {
console.error('连接错误', e)
this.close()
}
// 使用WebSocket的原生方法onmessage与服务器关联
this.socket.onmessage = (wsObj) => {
this.messageArr.push(wsObj.data)
}
}
sendFn(msg) {
// 使用WebSocket的原生方法send去发消息
this.socket.send(msg)
}
closeFn() {
// 使用WebSocket的原生方法close去关闭已经开启的WebSocket服务
this.socket.close()
this.socket = null // 回归默认值
this.messageArr = [] // 清空消息数组
}
}
这里的代码,还需要去做一些边界控制,再加一些判断即可
如果要使用的话,直接new一个myWebSocket即可(其实就是使用类编程的思想,给WebSocket再套一层壳子,封装思想)
使用的代码:
<template>
<div class="wsBox">
<el-button
size="mini"
class="wsOpen"
type="success"
icon="el-icon-check"
@click="openopen"
>开启WebSocket</el-button
>
<el-button
size="mini"
class="clientSend"
type="primary"
icon="el-icon-s-promotion"
@click="sendsend"
>客户端发送消息</el-button
>
<el-button
size="mini"
class="closeWs"
type="danger"
icon="el-icon-close"
@click="closeclose"
>关闭WebSocket</el-button
>
<el-button
size="mini"
class="serverMsgs"
type="info"
icon="el-icon-chat-dot-round"
@click="showMsgs"
>服务端推送的消息数组</el-button
>
<h3 v-for="(item, index) in msgs" :key="index">{{ item }}</h3>
</div>
</template>
<script>
import myWebSocket from "@/class/ws";
export default {
name: "wsRouteName",
data() {
return {
myWs: null,
};
},
created() {
this.myWs = new myWebSocket();
},
computed: {
msgs() {
return this.myWs.messageArr.slice(-5);
},
},
methods: {
openopen() {
this.myWs.createFn();
},
closeclose() {
this.myWs.closeFn();
},
sendsend() {
this.myWs.sendFn("111");
},
showMsgs() {
console.log("myWs.messageArr", this.myWs.messageArr);
},
},
beforeDestroy() {
this.myWs.closeFn();
},
};
</script>
完整代码在笔者的仓库里哦,欢迎各位道友,不吝star ^_^
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。