Alexander Kim
Alexander Kim

Reputation: 18401

How to reconnect a websocket connection after manual close - Vue

Here's my methods to open/close socket connection:

methods: {
  connect () {
    this.$socket.onopen = () => {
      this.status = 'connected'
      this.$socket.onmessage = ({data}) => {
        this.$socket.send(this.message)
        console.log({ event: "Recieved message", data })
      }
    }
    this.$socket.onclose = (e) => {
      console.log('Socket is closed. Reconnect will be attempted in 1 second.')
      setTimeout(() => {
        this.connect()
      }, 1000)
    }
  },
  disconnect () {
    this.$socket.close()
    this.status = 'disconnected'
  }
}

I'm not using socket.io etc, just built in Websocket object. When i manually call disconnect () method - it closes the connection as expected, but when i send message again - it says that connection is closed. Since i call connect () in a mounted, then it won't reconnect if i don't refresh the page.

I've tried using watcher:

watch: {
  '$socket': 'connect'
}

But no effect. Is there a way to watch for websocket connection status? If it's closed - call connect (), if it's error'ed - call connect () to reconnect it.

Upvotes: 3

Views: 6836

Answers (2)

Nike
Nike

Reputation: 107

You should check the close status code before reconnecting. e.code === 1e3 || e.code === 1001 || e.code === 1005

Upvotes: 0

Randy Casburn
Randy Casburn

Reputation: 14175

Your connect() method does nothing to "reconnect" to the WebSocket server. So calling this.connect() simply rewrites your onopen handler.

You have to take the steps necessary to reconnect to the WebSocket server. The most excellent answer to this question does a great job of explaining a great structure for your code:

vue: emitting global events from websocket listener

Unfortunately, it doesn't answer your specific question. So I've forked the sandbox from that answer and added the modified code below that allows you to achieve your goal.

import Vue from "vue";

const url = "wss://echo.websocket.org";
let socket;

const emitter = new Vue({
  methods: {
    send(message) {
      if (1 === socket.readyState) socket.send(message);
    },
    close() {
      if (1 === socket.readyState) {
        emitter.$emit("message", "Closing Socket.");
        socket.close();
        socket = null; // prevent memory leak
      }
    },
    connect() {
      socket = new WebSocket(url);
      socket.onmessage = function(msg) {
        emitter.$emit("message", msg.data);
      };
      socket.onerror = function(err) {
        emitter.$emit("error", err);
      };
      emitter.$emit("message", "Openning Socket.");
    }
  }
});

emitter.connect();

export default emitter;

To see how this service is used, check out index.js in the running sample is here: https://codesandbox.io/s/ry4993q654

Upvotes: 2

Related Questions