乐趣区

关于websocket:基于sockjs的前端WebSocket二次封装

因业务须要,与后端进行 websocket 长连贯通信,通过钻研,决定应用 sockjs-client 和 stompjs 库,并进行了二次封装。

package.json 版本:

"sockjs-client": "^1.5.1",
"stompjs": "^2.3.3",

socketManager.js:

import SockJS from 'sockjs-client';
import Stomp from 'stompjs';
import lodash from 'lodash';

function subscribeCallBack(data, subscribes) {if (data) {
        let topic = data.headers.destination;
        let funces = subscribes.get(topic);
        funces.forEach((func) => {func(data);
        });
    }
}

let clientManager = {
    client: null,
    connecting: false,// 是否正在连接
    subscribes: new Map(),// 订阅列表
    subscribe(topic, onMessage) {if (this.client != null && this.client.connected == true) {
            // 已连贯状态
            console.log('减少订阅 已连贯状态');
            if (!this.subscribes.has(topic)) {this.client.subscribe(topic, (data) => subscribeCallBack(data, this.subscribes));
                this.subscribes.set(topic, [onMessage]);
            } else {let funces = this.subscribes.get(topic);
                funces.push(onMessage);
            }
        } else {
            // 未连贯状态
            console.log('减少订阅 未连贯状态');
            if (!this.subscribes.has(topic)) {this.subscribes.set(topic, [onMessage]);
            } else {let funces = this.subscribes.get(topic);
                funces.push(onMessage);
            }
        }
    },
    subscribesAll() {console.log('订阅全副');
        if (lodash.isEmpty(this.client) || this.client.connected != true) {return;}
        let subscribes = this.subscribes;
        for (let topic of subscribes.keys()) {this.client.subscribe(topic, (data) => subscribeCallBack(data, subscribes));
        }
    },
    disconnect() {console.log('断开连接');
        if (lodash.isEmpty(this.client) || this.client.connected != true) {return;}
        this.client.disconnect();
        this.subscribes = new Map();},
    connect(onSuccess, onDisconnect) {
        try {if (this.connecting == true) {console.log('正在连接中');
                return;
            }
            this.connecting = true;
            if (lodash.isEmpty(this.client) || this.client.connected != true) {// 未连贯状态
                let socket = new SockJS('/bond/notification', null, { timeout: 6000});
                let stompClient = Stomp.over(socket);
                stompClient.debug = null;
                console.log('开始连贯');
                stompClient.connect
                    ({},
                        () => {
                            this.client = stompClient;
                            console.log('连贯胜利');
                            this.subscribesAll();// 连贯胜利后开始订阅所有内容
                            if (onSuccess != null && onSuccess != undefined) {onSuccess();
                            };
                        },
                        (error) => this.errorCallBack(error, onSuccess, onDisconnect)
                    );
            } else if (this.client != null && this.client.connected == true) {// 已连贯状态间接调用回调
                onSuccess();}
        }
        catch (err) {console.log('连贯异样', err);
        }
        finally {this.connecting = false;}
    },
    errorCallBack(error, onSuccess, onDisconnect) {console.log('连贯失败');
        if (onDisconnect != null && onDisconnect != undefined) {onDisconnect();
        }
        setTimeout(() => {// 主动重连
            console.log('从新连贯中');
            this.connect(onSuccess, onDisconnect);
        }, 10000);
    },
};

export default clientManager;

连贯形式:

useEffect(()=>{socketmanager.connect();
    return () => {socketmanager.disconnect();
    };
})

订阅形式:

 useEffect(() => {
        let topic = `/topic/notification`;
        socketmanager.subscribe(topic, (data) => {if (data) {//do something}
        })
    }, [])

如果有发现程序启动的时候报这个谬误:

须要批改下 connect 中央, 在申请胜利后再进行 connect,以确保 connect 在程序启动实现之后再被调用,如果还是不行,把曾经关上过的程序页面关掉,清空浏览器缓存再试试。具体起因临时未知,有大佬晓得的通知一下,哈哈~

作者:点墨
版权:本文版权归作者所有
转载:欢送转载,但未经作者批准,必须保留此段申明;必须在文章中给出原文连贯;否则必究法律责任

退出移动版