vue|websocket的简单应用

客户端(浏览器)和服务器端进行通信,只能由客户端发起ajax请求,才能进行通信,服务器端无法主动向客户端推送信息。为了解决这一问题,websocket因此产生。
1、新建一个node服务器

var app = require('express')(); var server = require('http').Server(app); var WebSocket = require('ws'); var wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', function connection(ws) { console.log('server: receive connection.'); ws.on('message', function incoming(message) { console.log('server: received: %s', message); }); setInterval(() => { ws.send('world'); }, 1000)}); app.listen(3000);

【vue|websocket的简单应用】通过node命令启动node服务器
2、建立前端web
> var ws = new WebSocket('ws://localhost:8080'); console.log(ws.readyState); ws.onopen = function () { console.log('ws onopen'); ws.send('from client: hello'); }; ws.onmessage = function (e) { console.log('ws onmessage'); console.log('from server: ' + e.data); }; ws.onclose = function (e) { console.log("断开了"); }ws.onerror = function () { console.log("出错了"); }

websocket常用的四个api:
onopen :建立连接 onmessage :连接通信 onclose :连接关闭 onerror :连接出错

WebSocket的当前状态:WebSocket.readyState
下面是WebSocket.readyState的四个值(四种状态):
0: 表示正在连接
1: 表示连接成功,可以通信了
2: 表示连接正在关闭
3: 表示连接已经关闭,或者打开连接失败
我们可以利用当前状态来做一些事情,比如上面栗子中当WebSocket链接成功后,才允许客户端发送ping。
if (this.ws.readyState === 1) { // 检查ws为链接状态 才可发送 this.ws.send('ping'); // 客户端发送ping }

当项目中很多地方使用WebSocket,把它封成一个class类,是更好的选择。
下面的栗子,做了非常详细的注释,建个html文件也可直接使用,websocket的常用API都放进去了。
下方注释的代码,先不用管,涉及到心跳机制,用于保持WebSocket连接的
class WebSocketClass { /** * @description: 初始化实例属性,保存参数 * @param {String} url ws的接口 * @param {Function} msgCallback 服务器信息的回调传数据给函数 * @param {String} name 可选值 用于区分ws,用于debugger */ constructor(url, msgCallback, name = 'default') { this.url = url; this.msgCallback = msgCallback; this.name = name; this.ws = null; // websocket对象 this.status = null; // websocket是否关闭 } /** * @description: 初始化 连接websocket或重连webSocket时调用 * @param {*} 可选值 要传的数据 */ connect(data) { // 新建 WebSocket 实例 this.ws = new WebSocket(this.url); this.ws.onopen = e => { // 连接ws成功回调 this.status = 'open'; console.log(`${this.name}连接成功`, e) // this.heartCheck(); if (data !== undefined) { // 有要传的数据,就发给后端 return this.ws.send(data); } } // 监听服务器端返回的信息 this.ws.onmessage = e => { // 把数据传给回调函数,并执行回调 // if (e.data =https://www.it610.com/article/=='pong') { //this.pingPong = 'pong'; // 服务器端返回pong,修改pingPong的状态 // } return this.msgCallback(e.data); } // ws关闭回调 this.ws.onclose = e => { this.closeHandle(e); // 判断是否关闭 } // ws出错回调 this.onerror = e => { this.closeHandle(e); // 判断是否关闭 } } // heartCheck() { //// 心跳机制的时间可以自己与后端约定 //this.pingPong = 'ping'; // ws的心跳机制状态值 //this.pingInterval = setInterval(() => { //if (this.ws.readyState === 1) { //// 检查ws为链接状态 才可发送 //this.ws.send('ping'); // 客户端发送ping //} //}, 10000) //this.pongInterval = setInterval(() => { //if (this.pingPong === 'ping') { //this.closeHandle('pingPong没有改变为pong'); // 没有返回pong 重启webSocket //} //// 重置为ping 若下一次 ping 发送失败 或者pong返回失败(pingPong不会改成pong),将重启 //console.log('返回pong') //this.pingPong = 'ping' //}, 20000) // } // 发送信息给服务器 sendHandle(data) { console.log(`${this.name}发送消息给服务器:`, data) return this.ws.send(data); } closeHandle(e = 'err') { // 因为webSocket并不稳定,规定只能手动关闭(调closeMyself方法),否则就重连 if (this.status !== 'close') { console.log(`${this.name}断开,重连websocket`, e) // if (this.pingInterval !== undefined && this.pongInterval !== undefined) { //// 清除定时器 //clearInterval(this.pingInterval); //clearInterval(this.pongInterval); // } this.connect(); // 重连 } else { console.log(`${this.name}websocket手动关闭`) } } // 手动关闭WebSocket closeMyself() { console.log(`关闭${this.name}`) this.status = 'close'; return this.ws.close(); } } function someFn(data) { console.log('接收服务器消息的回调:', data); } // const wsValue = https://www.it610.com/article/new WebSocketClass('ws://121.40.165.18:8800', someFn, 'wsName'); // 这个链接一天只能发送消息50次 const wsValue = https://www.it610.com/article/new WebSocketClass('wss://echo.websocket.org', someFn, 'wsName'); // 阮一峰老师教程链接 wsValue.connect('立即与服务器通信'); // 连接服务器 // setTimeout(() => { //wsValue.sendHandle('传消息给服务器') // }, 1000); // setTimeout(() => { //wsValue.closeMyself(); // 关闭ws // }, 10000)

vue版
> const heartCheck = { timeout: 60 * 1000, timer: null, serverTimer: null, reset() { this.timer && clearTimeout(this.timer) this.serverTimer && clearTimeout(this.serverTimer) }, start(ws) { this.reset() this.timer = setTimeout(() => { // console.log('发送心跳,后端收到后,返回一个心跳消息') // onmessage拿到返回的心跳就说明连接正常 ws.send(JSON.stringify({ heart: 1 })) this.serverTimer = setTimeout(() => { // 如果超过一定时间还没响应(响应后触发重置),说明后端断开了 ws.close() }, this.timeout) }, this.timeout) } } export default { name: 'Websocket', data() { return { asrc, wsuri: 'ws://123.207.167.163:9010/ajaxchattest', // ws wss lockReconnect: false, // 连接失败不进行重连 maxReconnect: 5, // 最大重连次数,若连接失败 socket: null } }, mounted() { this.initWebSocket() }, methods: { reconnect() { console.log('尝试重连') if (this.lockReconnect || this.maxReconnect <= 0) { return } setTimeout(() => { // this.maxReconnect-- // 不做限制 连不上一直重连 this.initWebSocket() }, 60 * 1000) }, initWebSocket() { try { if ('WebSocket' in window) { this.socket = new WebSocket(this.wsuri) } else { console.log('您的浏览器不支持websocket') } this.socket.onopen = this.websocketonopen this.socket.onerror = this.websocketonerror this.socket.onmessage = this.websocketonmessage this.socket.onclose = this.websocketclose } catch (e) { this.reconnect() } }, websocketonopen() { console.log('WebSocket连接成功', this.socket.readyState) heartCheck.start(this.socket) // this.socket.send('发送数据') this.websocketsend() }, websocketonerror(e) { console.log('WebSocket连接发生错误', e) this.reconnect() }, websocketonmessage(e) { // console.log(e) let data = https://www.it610.com/article/JSON.parse(e.data) console.log('得到响应', data) console.log('可以渲染网页数据...') // 消息获取成功,重置心跳 heartCheck.start(this.socket) }, websocketclose(e) { console.log('connection closed (' + e.code + ')') this.reconnect() }, websocketsend() { let data = https://www.it610.com/article/{ id:'a1b2c3' } this.socket.send(JSON.stringify(data)) } }, destroyed() { this.socket.close() } } ="scss" scoped>

    推荐阅读