4

I've configured a simple Vue project using the vue-cli tool:

vue init webpack my-project

Now I want to send some information through a web socket before the page gets rendered. Since I don't want to tie this logic to the Vue component, I have a different js file (named ws.js and based in this):

import Vue from 'vue'

const websocket = new WebSocket('ws://localhost:1234')

const emitter = new Vue({
  name: 'emitter',
  methods: {
    send (message) {
      websocket.send(JSON.stringify(message))
    }
  }
})

export default emitter

When the page loads, I use the emitter object to send some info:

<template>
    <div class="hello">
      TEST
    </div>
</template>

<script>
import emitter from '../ws/ws'
export default {
  name: 'HelloWorld',
  beforeMount () {
    emitter.send('Hello')
  }
}
</script>

And I get this error in Firefox console:

[Vue warn]: Error in beforeMount hook: "InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable"

found in

---> at src/components/HelloWorld.vue at src/App.vue

What am I doing wrong? Should I attach to a different event listener rather than beforeMount()? If I comment out the WebSocket related lines, the error disappears:

import Vue from 'vue'

// const websocket = new WebSocket('ws://localhost:1234')

const emitter = new Vue({
  name: 'emitter',
  methods: {
    send (message) {
      // websocket.send(message)
    }
  }
})

export default emitter
Aritz
  • 30,971
  • 16
  • 136
  • 217

1 Answers1

2

I need to write for the socket before it's in ready state before sending any message, so based in this answer I have changed ws.js to this:

import Vue from 'vue'

const websocket = new WebSocket('ws://localhost:1234')

// Make the function wait until the connection is made...
function waitForSocketConnection (socket, callback) {
  setTimeout(
    function () {
      if (socket.readyState === 1) {
        console.log('Connection is made')
        if (callback != null) {
          callback()
        }
      } else {
        console.log('wait for connection...')
        waitForSocketConnection(socket, callback)
      }
    }, 5) // wait 5 milisecond for the connection...
}

function sendWaiting (msg) {
  waitForSocketConnection(websocket, () => {
    console.log('Sending ' + msg)
    websocket.send(msg)
    console.log('Sent ' + msg)
  })
}

const emitter = new Vue({
  name: 'emitter',
  methods: {
    send (message) {
      sendWaiting(message)
    }
  }
})

export default emitter

Now, before sending any message the application checks if the WebSocket is ready and sends it, otherwise it rechecks each 5 milliseconds until it is.

Aritz
  • 30,971
  • 16
  • 136
  • 217