websocket 基础

构造函数

使用 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>
复制代码

拓展

WebSocket
零距离接触 websocket
WebSocket其实没那么难
你不知道的 WebSocket
WebSocket:5分钟从入门到精通
WebSocket探秘
websocket 断线重连

分类:
前端
标签: