4

基于sockjs的前端WebSocket二次封装

 2 years ago
source link: https://segmentfault.com/a/1190000040884244
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

基于sockjs的前端WebSocket二次封装

发布于 13 分钟前

因业务需要,与后端进行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
            }
        })
    }, [])

如果有发现程序启动的时候报这个错误:
1.png
需要修改下connect地方,在请求成功后再进行connect,以确保connect在程序启动完成之后再被调用,如果还是不行,把已经打开过的程序页面关掉,清空浏览器缓存再试试。具体原因暂时未知,有大佬知道的告诉一下,哈哈~

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK