构造函数
使用 WebSocket 构造函数来构造一个 ws 对象。
ws 对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的 API。
常量
① 正在连接:WebSocket.CONNECTING === 0;(WebSocket.prototype.CONNECTING = 0)
② 连接成功:WebSocket.OPEN === 1;(WebSocket.prototype.OPEN = 1)
③ 连接正在关闭:WebSocket.CLOSING === 2;(WebSocket.prototype.CLOSING = 2)
④ 连接已经关闭,或者打开连接失败:WebSocket.CLOSED === 3。(WebSocket.prototype.CLOSED = 3)
属性
① bufferedAmount:只读属性,返回已经被 send( ) 方法放入队列中但还没有被发送到网络中的数据的字节数。(一旦队列中的所有数据被发送至网络,则该属性值将被重置为 0。但是,若在发送过程中连接被关闭,则属性值不会重置为 0。如果你不断地调用 send( ),则该属性值会持续增长)。
ws.bufferedAmount === 0; // 发送完毕;
ws.bufferedAmount > 0; // 发送未结束;
② readyState: 只读属性,返回 WebSocket 的链接状态。(值为0~3其中之一)。
ws.readyState === WebSocket.CONNECTING; // 0: 正在链接中;
ws.readyState === WebSocket.OPEN; // 1: 已经链接并且可以通讯;
ws.readyState === WebSocket.CLOSING; // 2: 连接正在关闭;
ws.readyState === WebSocket.CLOSED; // 3: 连接已关闭或者没有链接成功;
方法
① close( ):关闭 WebSocket 连接或连接尝试(如果有的话)。 如果连接已经关闭,则此方法不执行任何操作。
ws.close(); // 关闭 WebSocket
② send( ):将需要通过 WebSocket 链接传输至服务器的数据排入队列,并根据所需要传输的 data bytes 的大小来增加 bufferedAmount 的值 。若数据无法传输(例如数据需要缓存而缓冲区已满)时,套接字会自行关闭。
ws.send('发送数据~'); // 向服务器发送数据;
事件
① onopen:定义一个事件处理程序,当 WebSocket 的连接状态 readyState 变为 1 时调用,这意味着当前连接已经准备好发送和接受数据。这个事件处理程序通过事件(建立连接时)触发。
// 写法一:
ws.onopen = (e) => { console.log('websocket连接成功~'); };
// 写法二:
ws.addEventListener('open', (e)=>{ console.log('websocket连接成功~'); });
② onmessage:message 事件会在 WebSocket 接收到新消息时被触发。
// 写法一:
ws.onmessage = (e) => { console.log('websocket接收消息~'); };
// 写法二:
ws.addEventListener('message', (e)=>{ console.log('websocket接收消息~'); });
③ onclose:返回一个事件监听器,这个事件监听器将在 WebSocket 连接的 readyState 变为 CLOSED 时被调用,它接收一个名字为 close 的 CloseEvent 事件。
// 写法一:
ws.onclose = (e) => { console.log('websocket连接关闭~'); };
// 写法二:
ws.addEventListener('close', (e)=>{ console.log('websocket连接关闭~'); });
④ onerror:当 websocket 的连接由于一些错误事件的发生 (例如无法发送一些数据) 而被关闭时,一个 error 事件将被引发。
// 写法一:
ws.onerror = (e) => { console.log('websocket报错了~'); };
// 写法二:
ws.addEventListener('error', (e)=>{ console.log('websocket报错了~'); });
完整示例(上)
// src/utils/websocketServer.js:
const readyState = {
CONNECTING: 0, // 正在连接;
OPEN: 1, // 连接成功;
CLOSING: 2, // 连接正在关闭;
CLOSED: 3, // 连接已经关闭,或者打开连接失败;
};
class WebsocketServer {
ws = {}; // websocket对象;
hostAddress = null; // 长连接地址;
callback = null; // 接收websocket消息的回调方法;
timer = null;
connectLimitTimes = 3; // 重连限制次数;
constructor(opts) {
const { hostAddress, callback } = opts;
this.hostAddress = hostAddress;
this.callback = callback;
}
/**
* 初始化websocket;
*/
initWebsocket() {
const { hostAddress } = this;
this.ws = new WebSocket(hostAddress);
this.open();
this.close();
this.message();
this.error();
this.timer = setInterval(() => {
const ready = this.ws.readyState;
if (ready === readyState.OPEN) {
if (this.ws.bufferedAmount === 0) {
// 发送完毕;
this.send('ping ~ 心跳包');
} else {
// 发送未结束;
}
}
if (ready === readyState.CLOSED) {
if (this.connectLimitTimes > 0) {
this.connectLimitTimes--;
this.reconnect();
} else {
clearInterval(this.timer);
}
}
}, 1000);
}
/**
* 连接成功后的回调方法;
*/
open() {
this.ws.addEventListener('open', (e) => {
this.connectLimitTimes = 3;
console.log('websocket连接成功~');
});
}
/**
* 长连接关闭后的回调方法;
*/
close() {
this.ws.addEventListener('close', (e) => {
console.log('websocket连接关闭~');
});
}
/**
* 接收服务器数据后的回调方法;
*/
message() {
this.ws.addEventListener('message', (e) => {
this.callback && this.callback(e);
console.log('websocket接收消息~', e);
});
}
/**
* 向服务器发送数据;
*/
send(msg) {
this.ws.send(msg);
}
/**
* 报错时的回调方法;
*/
error() {
this.ws.addEventListener('error', (e) => {
console.log('websocket报错了~');
});
}
/**
* 关闭websocket;
*/
handleClose() {
const { ws } = this;
if (ws.readyState === readyState.OPEN) {
ws.close();
}
}
/**
* 重连;
*/
reconnect() {
if (this.timer) clearInterval(this.timer);
this.initWebsocket();
}
}
export default WebsocketServer;
// src/App.vue:
<script>
export default {
data(){
return {
wsServer: null, // websocket服务;
}
},
mounted(){
this.initWebsocketServer();
},
methods: {
/**
* 实例化websocket服务;
*/
initWebsocketServer() {
const hostAddress = `ws://192.168.58.204:9090/notice/websocket/20220301/22070062`;
this.wsServer = new WebsocketServer({
hostAddress,
callback(e) {
console.log('websocket接收的数据:', e);
},
});
this.wsServer.initWebsocket();
}
}
}
</script>
完整示例(下)
对上面的示例进行改进
// src/utils/websocketServer.ts:
const readyState = {
CONNECTING: 0, // 正在连接;
OPEN: 1, // 连接成功;
CLOSING: 2, // 连接正在关闭;
CLOSED: 3, // 连接已经关闭,或者打开连接失败;
};
class WebsocketServer {
ws: any = {}; // websocket对象;
hostAddress: any = null; // 长连接地址;
timer: any = null;
connectLimitTimes: number = 0; // 重连限制次数;
constructor(opts: { hostAddress: any }) {
const { hostAddress } = opts;
this.hostAddress = hostAddress;
}
/**
* 初始化websocket;
*/
initWebsocket(connectedCallback: any, receiveMsgCallback: any, connectFailedCallback: any, connectLimitTimes: number) {
const { hostAddress } = this;
this.connectLimitTimes = connectLimitTimes;
this.ws = new WebSocket(hostAddress);
this.open(connectedCallback);
this.close();
this.message(receiveMsgCallback);
this.error();
clearInterval(this.timer);
this.timer = setInterval(() => {
const ready = this.ws.readyState;
if (ready === readyState.OPEN) {
if (this.ws.bufferedAmount === 0) {
// 发送完毕;
// this.send('ping ~ 心跳包');
} else {
// 发送未结束;
}
}
if (ready === readyState.CLOSED) {
if (this.connectLimitTimes > 0) {
this.connectLimitTimes--;
this.reconnect(connectedCallback, receiveMsgCallback, connectFailedCallback, this.connectLimitTimes);
} else {
connectFailedCallback && connectFailedCallback();
clearInterval(this.timer);
}
}
}, 100);
}
/**
* 连接成功后的回调方法;
*/
open(connectedCallback: any) {
this.ws.addEventListener('open', (e: any) => {
connectedCallback && connectedCallback(e);
console.log('websocket连接成功~');
});
}
/**
* 长连接关闭后的回调方法;
*/
close() {
this.ws.addEventListener('close', (e: any) => {
console.log('websocket连接关闭~');
});
}
/**
* 接收服务器数据后的回调方法;
*/
message(receiveMsgCallback: any) {
this.ws.addEventListener('message', (e: any) => {
receiveMsgCallback && receiveMsgCallback(e);
console.log('websocket接收消息~', e);
});
}
/**
* 向服务器发送数据;
*/
send(msg: any) {
this.ws.send(msg);
}
/**
* 报错时的回调方法;
*/
error() {
this.ws.addEventListener('error', (e: any) => {
console.log('websocket报错了~');
});
}
/**
* 关闭websocket;
*/
handleClose() {
const { ws } = this;
if (ws.readyState === readyState.OPEN) {
ws.close();
}
}
/**
* 重连;
*/
reconnect(connectedCallback: any, receiveMsgCallback: any, connectFailedCallback: any, connectLimitTimes: any) {
if (this.timer) clearInterval(this.timer);
this.initWebsocket(connectedCallback, receiveMsgCallback, connectFailedCallback, connectLimitTimes);
}
}
export default WebsocketServer;
//src/App.vue:
import WebsocketServer from './utils/websocketServer';
import { onMounted, ref } from 'vue';
import bus from '@/utils/bus';
let wsServer = ref();
onMounted(() => {
localStorage.setItem('ws_host', '127.0.0.1');
initWebsocketServer();
});
/**
* 实例化websocket服务;
*/
const initWebsocketServer = () => {
const hostAddress = `ws://${localStorage.getItem('ws_host')}:21001/printList`;
wsServer.value = new WebsocketServer({
hostAddress,
});
// @ts-ignore
window.scmWs = wsServer.value;
};
//src/utils/common.ts:
/**
* 获取ws状态;
*/
const getWsStatus = () => {
return window.scmWs.ws.readyState;
};
//src/views/material/materialInfor/hooks/usePurchasConfig.ts:
import { getWsStatus, getPrinterList, isJsonString } from '@/utils/common';
const wsStatus = getWsStatus();
if (wsStatus === 1) {
getPrinterList();
getSourceCodeInfo(row);
} else {
initWs(
() => {
getPrinterList();
getSourceCodeInfo(row);
},
(e: any) => {
if (e.data === 'success') {
} else if (isJsonString(e.data)) {
bus.emit('printList', JSON.parse(e.data));
} else {
msgError({ msg: e.data });
}
},
() => {
sourceCodeBtnLoading.value = false;
msgError({ msg: '请下载并安装打印组件,如果已安装请先打开再打印!' });
},
0,
);
}
拓展
WebSocket
零距离接触 websocket
WebSocket其实没那么难
你不知道的 WebSocket
WebSocket:5分钟从入门到精通
WebSocket探秘
websocket 断线重连