前言:
如果项目中多个组件都使用到WebSocket请求,那么我们需要对WebSocket进行封装,方便我们使用。
下面我根据我的项目结构来创建文件和引入文件,大家注意一下自己项目结构。
一、在utils目录下创建websocket.js文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | import { Message } from 'element-ui' import { getToken } from '@/utils/authToken' // 与后端的协商,websocket请求需要带上token参数 let websock = null let messageCallback = null let errorCallback = null let wsUrl = '' // 接收ws后端返回的数据 function websocketonmessage (e) { messageCallback(JSON.parse(e.data)) } /** * 发起websocket连接 * @param {Object} agentData 需要向后台传递的参数数据 */ function websocketSend (agentData) { // 加延迟是为了尽量让ws连接状态变为OPEN setTimeout(() => { // 添加状态判断,当为OPEN时,发送消息 if (websock.readyState === websock.OPEN) { // websock.OPEN = 1 // 发给后端的数据需要字符串化 websock.send(JSON.stringify(agentData)) } if (websock.readyState === websock.CLOSED) { // websock.CLOSED = 3 console.log('websock.readyState=3') Message.error('ws连接异常,请稍候重试') errorCallback() } }, 500) } // 关闭ws连接 function websocketclose (e) { // e.code === 1000 表示正常关闭。 无论为何目的而创建, 该链接都已成功完成任务。 // e.code !== 1000 表示非正常关闭。 if (e && e.code !== 1000) { Message.error('ws连接异常,请稍候重试') errorCallback() } } // 建立ws连接 function websocketOpen (e) { // console.log('ws连接成功') } // 初始化weosocket function initWebSocket () { if (typeof (WebSocket) === 'undefined') { Message.error('您的浏览器不支持WebSocket,无法获取数据') return false } const token = 'JWT=' + getToken() // ws请求完整地址 const requstWsUrl = wsUrl + '?' + token websock = new WebSocket(requstWsUrl) websock.onmessage = function (e) { websocketonmessage(e) } websock.onopen = function () { websocketOpen() } websock.onerror = function () { Message.error('ws连接异常,请稍候重试') errorCallback() } websock.onclose = function (e) { websocketclose(e) } } /** * 发起websocket请求函数 * @param {string} url ws连接地址 * @param {Object} agentData 传给后台的参数 * @param {function} successCallback 接收到ws数据,对数据进行处理的回调函数 * @param {function} errCallback ws连接错误的回调函数 */ export function sendWebsocket (url, agentData, successCallback, errCallback) { wsUrl = url initWebSocket() messageCallback = successCallback errorCallback = errCallback websocketSend(agentData) } /** * 关闭websocket函数 */ export function closeWebsocket () { if (websock) { websock.close() // 关闭websocket websock.onclose() // 关闭websocket } } |
二、在vue组件中使用WebSocket封装好的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <template> <div> <button @click="requstWs">点击发起websocket请求</button> </div> </template> <script> import { sendWebsocket, closeWebsocket } from '@/utils/websocket.js' export default { beforeDestroy () { // 页面销毁时关闭ws。因为有可能ws连接接收数据尚未完成,用户就跳转了页面 // 在需要主动关闭ws的地方都可以调用该方法 closeWebsocket() }, methods: { // ws连接成功,后台返回的ws数据,组件要拿数据渲染页面等操作 wsMessage (data) { const dataJson = data console.log(dataJson) // 这里写拿到数据后的业务代码 }, // ws连接失败,组件要执行的代码 wsError () { // 比如取消页面的loading }, requstWs () { // 防止用户多次连续点击发起请求,所以要先关闭上次的ws请求。 closeWebsocket() // 跟后端协商,需要什么参数数据给后台 const obj = { monitorUrl: 'xxxxxxxxxxxxx', userName: 'xxxxxxxxxx' } // 发起ws请求 sendWebsocket('ws://test.ws.com', obj, this.wsMessage, this.wsError) } } } </script> |
介绍WebSocket对象中的readyState属性
WebSocket的readyState属性用来定义连接状态,该属性的值有下面几种:
0 :对应常量 CONNECTING
正在建立连接连接,还没有完成。
1 :对应常量 OPEN
连接成功建立,可以进行通信。
2 :对应常量 CLOSING
连接正在进行关闭握手,即将关闭。
3 : 对应常量 CLOSED
连接已经关闭或者根本没有建立。
介绍WebSocket断开连接onclose的重要信息错误状态码
WebSocket断开时,会触发CloseEvent, CloseEvent会在连接关闭时发送给使用 WebSockets 的客户端. 它在 WebSocket 对象的 onclose 事件监听器中使用。CloseEvent的code字段表示了WebSocket断开的原因。可以从该字段中分析断开的原因。
CloseEvent有三个字段需要注意, 通过分析这三个字段,一般就可以找到断开原因。
1 2 3 | CloseEvent.code: code是错误码,是整数类型 CloseEvent.reason: reason是断开原因,是字符串 CloseEvent.wasClean: wasClean表示是否正常断开,是布尔值。一般正常断开时,该值为true |
如下是在关闭ws连接的时候打印出来的CloseEvent对象:
关闭状态码表
下面标红的状态码是我在项目中测试遇到过的。
状态码 | 描述 |
---|---|
0–999 | 保留段, 未使用 |
正常关闭; 无论为何目的而创建, 该链接都已成功完成任务. | |
1001 | 终端离开, 可能因为服务端错误, 也可能因为浏览器正从打开连接的页面跳转离开. |
1002 | 由于协议错误而中断连接. |
1003 | 由于接收到不允许的数据类型而断开连接 (如仅接收文本数据的终端接收到了二进制数据). |
1004 | 保留. 其意义可能会在未来定义. |
1005 | 保留. 表示没有收到预期的状态码. |
保留. 用于期望收到状态码时连接非正常关闭 (也就是说, 没有发送关闭帧). | |
1007 | 由于收到了格式不符的数据而断开连接 (如文本消息中包含了非 UTF-8 数据). |
1008 | 由于收到不符合约定的数据而断开连接. 这是一个通用状态码, 用于不适合使用 1003 和 1009 状态码的场景. |
1009 | 由于收到过大的数据帧而断开连接. |
1010 | 客户端期望服务器商定一个或多个拓展, 但服务器没有处理, 因此客户端断开连接. |
客户端由于遇到没有预料的情况阻止其完成请求, 因此服务端断开连接. | |
1012 | 服务器由于重启而断开连接. |
1013 | 服务器由于临时原因断开连接, 如服务器过载因此断开一部分客户端连接. |
1014 | 由 WebSocket标准保留以便未来使用. |
1015 | 保留. 表示连接由于无法完成 TLS 握手而关闭 (例如无法验证服务器证书). |
1016–1999 | 由 WebSocket标准保留以便未来使用. |
2000–2999 | 由 WebSocket拓展保留使用. |
如果你的服务所用的协议是HTTPS的,那么使用的WebSocket协议也必须是wss, 而不能是ws
参考资料链接:
https://www.cnblogs.com/scott-j/p/9306197.html
https://segmentfault.com/a/1190000014582485?utm_source=tag-newest
https://blog.csdn.net/qq_39186346/article/details/81941664