platypush/platypush/backend/http/webapp/src/Events.vue

187 lines
4.2 KiB
Vue
Raw Normal View History

2020-11-27 23:12:10 +01:00
<template>
<div/>
</template>
2020-11-21 01:12:08 +01:00
<script>
import { bus } from "@/bus";
2020-11-21 01:12:08 +01:00
export default {
name: "Events",
props: {
wsPort: {
type: Number,
default: 8009,
}
},
2020-11-21 01:12:08 +01:00
data() {
return {
ws: null,
initialized: false,
2020-11-21 01:12:08 +01:00
pending: false,
opened: false,
timeout: null,
reconnectMsecs: 30000,
handlers: {},
handlerNameToEventTypes: {},
2020-11-21 01:12:08 +01:00
}
},
methods: {
onWebsocketTimeout() {
2020-12-09 20:40:22 +01:00
console.log('Websocket reconnection timed out, retrying')
this.pending = false
if (this.ws)
this.ws.close()
this.onClose()
},
onMessage(event) {
const handlers = []
event = event.data
if (typeof event === 'string') {
try {
event = JSON.parse(event)
} catch (e) {
console.warn('Received invalid non-JSON event')
console.warn(event)
}
}
console.debug(event)
if (event.type !== 'event') {
// Discard non-event messages
2020-11-21 01:12:08 +01:00
return
}
2021-04-06 21:10:48 +02:00
if (null in this.handlers) { // lgtm [js/implicit-operand-conversion]
handlers.push(this.handlers[null]) // lgtm [js/implicit-operand-conversion]
}
2020-11-21 01:12:08 +01:00
if (event.args.type in this.handlers) {
handlers.push(...Object.values(this.handlers[event.args.type]))
2020-11-21 01:12:08 +01:00
}
for (let handler of handlers) {
if (!handler)
continue
if (handler instanceof Array)
handler = handler[0]
else if (handler instanceof Object && !(handler instanceof Function))
handler = Object.values(handler)[0]
handler(event.args)
}
},
2020-11-21 01:12:08 +01:00
onOpen() {
if (this.opened) {
console.log("There's already an opened websocket connection, closing the newly opened one")
2020-12-09 20:40:22 +01:00
if (this.ws) {
this.ws.onclose = () => {}
this.ws.close()
}
}
2020-11-21 01:12:08 +01:00
console.log('Websocket connection successful')
this.opened = true
2020-11-21 01:12:08 +01:00
if (this.pending) {
this.pending = false
}
2020-11-21 01:12:08 +01:00
if (this.timeout) {
clearTimeout(this.timeout)
this.timeout = undefined
}
},
2020-11-21 01:12:08 +01:00
onError(error) {
console.error('Websocket error')
console.error(error)
},
2020-11-21 01:12:08 +01:00
onClose(event) {
if (event) {
console.log('Websocket closed - code: ' + event.code + ' - reason: ' + event.reason)
2020-11-21 01:12:08 +01:00
}
this.opened = false
2020-11-21 01:12:08 +01:00
if (!this.pending) {
this.pending = true
this.init()
}
},
2020-11-21 01:12:08 +01:00
init() {
try {
2021-01-30 23:21:52 +01:00
const protocol = location.protocol === 'https:' ? 'wss' : 'ws'
const url = `${protocol}://${location.hostname}:${this.wsPort}`
this.ws = new WebSocket(url)
} catch (err) {
console.error('Websocket initialization error')
console.error(err)
return
}
2020-11-21 01:12:08 +01:00
this.pending = true
this.timeout = setTimeout(this.onWebsocketTimeout, this.reconnectMsecs)
this.ws.onmessage = this.onMessage
this.ws.onopen = this.onOpen
this.ws.onerror = this.onError
this.ws.onclose = this.onClose
this.initialized = true
},
subscribe(msg) {
const handler = msg.handler
const events = msg.events.length ? msg.events : [null]
const handlerName = msg.handlerName
for (const event of events) {
if (!(event in this.handlers)) {
this.handlers[event] = {}
2020-11-21 01:12:08 +01:00
}
if (!(handlerName in this.handlerNameToEventTypes)) {
this.handlerNameToEventTypes[handlerName] = events
}
this.handlers[event][handlerName] = handler
}
return () => {
this.unsubscribe(handlerName)
2020-11-21 01:12:08 +01:00
}
},
2020-11-21 01:12:08 +01:00
unsubscribe(handlerName) {
const events = this.handlerNameToEventTypes[handlerName]
if (!events)
return
2020-11-21 01:12:08 +01:00
for (const event of events) {
if (!this.handlers[event]?.[handlerName])
continue
2020-11-21 01:12:08 +01:00
delete this.handlers[event][handlerName]
if (!Object.keys(this.handlers[event]).length)
delete this.handlers[event]
2020-11-21 01:12:08 +01:00
}
delete this.handlerNameToEventTypes[handlerName]
},
2020-11-21 01:12:08 +01:00
},
created() {
bus.on('subscribe', this.subscribe)
bus.on('unsubscribe', this.unsubscribe)
2020-11-21 01:12:08 +01:00
this.init()
},
}
</script>