隨著互聯網的快速發展,程序員需要處理的業務場景也越來越多了,ajax對于一些常鏈接實時刷新數據特殊的場景的處理就顯的很無力,于是webSocket出現了。
這次的博客將以websocket的鏈接,發送,監聽,關閉,重連,重發幾個步驟來講解一下websocket的使用。
我將會封裝一個websocket的構造函數來講。
1 構建獲取基本信息
class LangWs {
constructor(url) {
this.ws = '';
this.url = url;
this.connect()
}
connect() { // ws鏈接
this.ws = new WebSocket(this.url)
}
wsStatus() { // ws狀態
return this.ws.readyState
}
}
2 發送消息
class LangWs {
constructor(url) {
this.ws = '';
this.url = url;
this.connect()
}
connect() {
this.ws = new WebSocket(this.url);
}
send(args) { // 發送
this.ws.send(args)
}
wsStatus() {
return this.ws.readyState
}
}
3 接受
class LangWs {
constructor(url) {
this.ws = '';
this.handers = new Map(); // 處理回調函數
this.url = url;
this.connect()
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onmessage = (event) => {
// 解析發過來的數據,看情況解壓
if (this.handers.has(event.data.cmd)) {
this.handers.get(event.data.cmd)()
}
};
}
send(args) {
this.ws.send(args)
}
addHandler(cmd, fn) {
this.handers.set(cmd,fn)
}
wsStatus() {
return this.ws.readyState
}
}
4 關閉
class LangWs {
constructor(url) {
this.ws = '';
this.forceClose=false; // 用于判斷是否重連
this.handers = new Map();
this.url = url;
this.connect()
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onmessage = (event) => {
// 解析發過來的數據,看情況解壓
if (this.handers.has(event.data.cmd)) {
this.handers.get(event.data.cmd)()
}
};
}
send(args) {
this.ws.send(args)
}
addHandler(cmd, fn) {
this.handers.set(cmd,fn)
}
close() {
if (this.ws) {
this.forceClose = true;
this.ws.close()
}
}
wsStatus() {
return this.ws.readyState
}
}
5 重連
class LangWs {
constructor(url) {
this.ws = '';
this.forceClose=false; // 用于判斷是否重連
this.reconnectInterval=1000; // 用于重連
this.handers = new Map();
this.url = url;
this.connect()
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onmessage = (event) => {
// 解析發過來的數據,看情況解壓
if (this.handers.has(event.data.cmd)) {
this.handers.get(event.data.cmd)()
}
};
this.ws.onclose = () => {
if (this.forceClose) return; // 手動關閉,則關閉
setTimeout(() => { // 重連
this.connect();
}, this.reconnectInterval);
}
}
send(args) {
this.ws.send(args)
}
addHandler(cmd, fn) {
this.handers.set(cmd,fn)
}
close() {
if (this.ws) {
this.forceClose = true;
this.ws.close()
}
}
wsStatus() {
return this.ws.readyState
}
}
6 重發以及其他一些判斷(都有備注)
class LangWs {
constructor(url) {
this.ws = ''; // ws實例
this.wsStatus = ''; // ws狀態
this.reconnectInterval = 1000; // 重發事件
this.forceClose = false; // 判斷是否重發
this.handers = new Map(); // 處理發送事件集合
this.subChannels = new Map(); // 重發事件集合
this.url = url; // ws url
this.connect() // 連接函數
}
connect() {
this.ws = new WebSocket(this.url);
this.wsStatus = this.ws.readyState;
if (this.wsStatus > 1) {
if (this.forceClose) {
return;
}
}
this.ws.onopen = () => { // 處理open事件
if (this.subChannels && this.subChannels.size) { // 重發事件
this.subChannels.forEach((item) => {
const args = {
event: 'sub',
params: item
};
this.send(JSON.stringify(args));
});
}
};
this.ws.onmessage = (event) => { // 處理回調函數
// 解析發過來的數據,看情況解壓
if (this.handers.has(event.data.cmd)) {
this.handers.get(event.data.cmd)()
}
};
this.ws.onclose = () => { // 判斷是否重發
if (this.forceClose) return;
setTimeout(() => {
this.connect();
}, this.reconnectInterval);
}
}
send(args) { // 發送數據
if (this.wsStatus === WebSocket.OPEN) {
this.ws.send(args);
this.resetSub(args.cmd) //記錄發過的消息
}
}
// 添加處理函數
addHandler(cmd, fn) {
this.handers.set(cmd,fn)
}
removeHandler(cmd) { // 刪除處理函數
if (cmd) {
this.handers.delete(cmd); // 刪除事件
if (this.subChannels.has(cmd)) {
this.subChannels.delete(cmd);
}
}
}
resetSub(data) { // 消息處理函數
if (typeof data !== 'string') {
return;
}
const reqData = JSON.parse(data);
if (reqData.event === 'sub') { // 處理添加事件
this.subChannels.set(cmd, reqData.params);
}
}
close() { // 主動關閉
if (this.ws) {
this.forceClose = true;
this.ws.close()
}
}
}
還有一些心跳檢查,事件處理可以自行配置,這個配置已經適合絕大多數場景了
最后在加一個使用案例;根據自己的數據格式來,做一些適當的改進。
import {LangWs} from './ws' // 寫入自己文件路徑
const socket = new LangWs('ws://localhost8080:80');
const args = {
id: '12121',
cmd: 'qqqqqqq'
};
socket.send(args);
socket.addHandler(args.cmd, (data) => {
console.log(11) // 這里處理自己的業務
});
socket.removeHandler(args.cmd); //在自己需要的地方斷開
socket.close(); //在自己需要的地方關閉連接