Use stompjs to implement Websocket instant messaging subscription and publishing

Instant messaging is often used in daily development to achieve real-time updates of messages.

1. Use polling for query (if the status does not change for a long time under a certain situation, the client’s frequent calling of the interface will cause a waste of resources)

2. Use websockets

The following examples use stompjs and sockjs-client to achieve message subscription and publishing.

npm install –save stompjs

npm install –save sockjs-client

Without further ado, let’s get straight to the code.

1. The following can encapsulate the independent file stompManager.js

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

const ip = '192.168.4.46' // Can be configured based on external variables
const stompManager = {
    url: 'http://' + ip + ':8081/web', // Connection address (defined by the front and back ends)
    header: null, // Connect header
    checkInterval: null, //Check whether the connection is successfully established when disconnected and reconnected
    websocket: null,
    stompClient: null,
    listenerList: [], //Listener list, used to re-register listening when disconnected and reconnected (mainly subscriptions added after other pages)
    // isReconnect: true, // Whether to reconnect (you can define whether to reconnect according to the configuration)
    init(header) {
        console.log('stompManager---init-----', this)
        //The content in the header is passed as needed, for example: {userId: store.state.user.userId, type: 'WEB'}
        this.header = header
        this.listenerList = []
        // this.isReconnect = true
        this.connect()
    },
    connect(){
        if(this.stompClient != null & amp; & amp; this.websocket.readyState === SockJS.OPEN){ // Connected
            this.stompClient.disconnect(()=>{
                this.connect()
            })
            return ;
        }else if(this.stompClient != null & amp; & amp; this.websocket.readyState === SockJS.CONNECTING){ // Connecting
            // console.log("Connection is being established")
            return;
        }
        const _this = this
        this.websocket = new SockJS(this.url);

        // Get the client object of the STOMP subprotocol
        const stompClient = Stomp.over(this.websocket);
        stompClient.debug = null //Close console printing
        stompClient.heartbeat.outgoing = 20000;
        stompClient.heartbeat.incoming = 0;//The client does not receive heartbeat packets from the server
        //Initiate a websocket connection to the server
        stompClient.connect(
            this.header, //Be careful to change your username here. It is best to bring it in as a parameter.
            frame => {
                console.log('Link successful!')
                _this.listenerList.forEach((item, index)=>{
                    _this.listenerList[index].subscription = _this.stompClient.subscribe(item.topic,item.callback)
                })
                //unsubscribe() can be used to cancel the client's subscription to this destination destination
                // stompClient.subscribe("/user/queue/message", msg => {
                // // this.getData(msg);
                // console.log(msg)
                // });

                //Subscribe to the red dot message destination and subscribe directly after the connection is successfully established.
                _this.stompClient.subscribe('/user/queue/message', function(response) {
                    const data = JSON.parse(response.body)
                    console.log(data) // Define it according to the situation
                })
            },
            err => { // This function will be called when the first connection fails and when the connection is disconnected. Reconnection is called here. Active calling disconnect will not go here.
                // console.log('stompClient-----connect---error----', err)
                // if (_this.isReconnect) { // Need to reconnect
                    setTimeout(() => {
                        _this.connect()
                    }, 2000)
                // }
            }
        );
        this.stompClient = stompClient
    },
    disconnect() {
        // this.isReconnect = false
        if (this.stompClient & amp; & amp; this.stompClient.connected) { // Currently connected
            this.stompClient.disconnect(()=>{
                console.log('Disconnect actively and do not reconnect---------')
            })
        }
    },
    send(topic, params, callback, responseTopic) { // External call, send message
        if (this.stompClient & amp; & amp; this.stompClient.connected) { // Currently connected
            if (responseTopic) { // After this message is sent, there will be a reply message corresponding to the response topic
                var i = 1
                var self = this
                this.subscribe(responseTopic, function(response) {
                    console.log(responseTopic + '-------', response)
                    var data = JSON.parse(response.body)
                    if (data.status == '200') { // Request successful
                        self.stompClient.unsubscribe(responseTopic)
                        if (callback) callback({success:true, data:data})
                    }else { // Request failed
                        console.log('Number of repeated sendings--------', i)
                        if (i >= 5) { // No more requests if more than 5 times
                            self.stompClient.unsubscribe(responseTopic)
                            if (callback) callback({success:false, msg:data.msg})
                        }else {
                            i++
                            setTimeout(() => {
                                self.stompClient.send(topic,{},JSON.stringify(params));
                            }, 2000);
                        }
                    }
                })
            }
            this.stompClient.send(topic,{},JSON.stringify(params));
        }else {
            if (callback) callback({success:false, msg:'Not connected'})
        }
    },
    unsubscribe(topic){ // External call, unsubscribe
        for(let i=0;i<this.listenerList.length;i + + ){
            if(this.listenerList[i].topic == topic){
                var subscription = this.listenerList[i].subscription
                if (subscription) {
                    subscription.unsubscribe()
                }
                this.listenerList.splice(i,1)
                console.log("Unsubscribe:" + topic + " size:" + this.listenerList.length)
                break;
            }
        }
    },
    subscribe(topic, callback) { // External call, subscribe
        if (this.stompClient & amp; & amp; this.stompClient.connected) {
            if (this.listenerList.some(item => item.topic == topic)) { // I have subscribed before and need to unsubscribe.
                this.unsubscribe(topic)
            }
            var subscription = this.stompClient.subscribe(topic, callback)
            this.listenerList.push({
                topic: topic,
                callback: callback,
                subscription: subscription
            })
        }else {
            var flag = false
            for(let i=0; i<this.listenerList.length; i + + ){
                if(this.listenerList[i].topic == topic){
                    flag = true
                    this.listenerList[i].callback = callback
                    console.log("Subscription:" + topic + " size:" + this.listenerList.length)
                    break;
                }
            }
            if (!flag) { // This topic has not been monitored before
                this.listenerList.push({
                    topic: topic,
                    callback: callback
                })
            }
        }
    }
}

export default stompManager

2. Main.js file introduction

import Vue from 'vue'
import socket from './libs/stompManager' // Modify according to the file path

Vue.prototype.$socket = socket // Global configuration

3. Connect and disconnect calls (the scheme can be adopted, connect when logging in and refreshing the page, disconnect when logging out)

import stompManager from '@/libs/stompManager' // Pay attention to the file address

stompManager.disconnect() // Disconnect websocket connection

stompManager.init(header) //Initialize connection header type:Object

4. Other files call subscription and unsubscribe

// Subscribe
this.$socket.subscribe('/topic/publish/', (response)=>{
    var data = JSON.parse(response.body)
})

// unsubscribe
this.$socket.unsubscribe('/topic/publish/')

This is some summary I made in my work and study, and I also share it with friends who need it ~ For reference and study, if you have any suggestions, please leave a comment. Please indicate the source when reprinting, thank you for your support!