Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | 1x 1x 4x 5x 5x 4x 9x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 6x 5x 5x 1x 1x 1x 1x 12x 6x 6x 6x 6x 6x 16x | // @ts-check import { forEach, hasIn, invoke } from "lodash"; import Vue from "vue"; import ErrorHandlerMixin from "../mixins/BaseErrorHandlerMixin"; import d from "debug"; const debug = d("base:es"); /** * @typedef {{ * source: EventSource|null, * listeners: { [key: string]: (e: MessageEvent) => void }|null * }} Opts */ const component = /** @type {V.Constructor<Opts, any>} */(Vue).extend({ name: "BaseEventSource", mixins: [ ErrorHandlerMixin ], props: { src: { type: String, default: null }, json: { type: Boolean, default: false } }, /** @return {{ message: any }} */ data() { return { message: null }; }, watch: { src: { immediate: true, handler() { this.release(); this.connect(); } } }, beforeDestroy() { this.release(); }, methods: { release() { if (this.$options.source) { debug("closing EventSource(%s)", this.src); forEach(this.$options.listeners, // @ts-ignore // eslint-disable-next-line @stylistic/js/max-len (listener, name) => this.$options.source.removeEventListener(name, listener)); this.$options.source.close(); this.$options.source = null; this.$options.listeners = null; } }, connect() { Iif (this.$options.source || !this.src) { return; } debug("opening EventSource(%s)", this.src); this.$options.source = new EventSource(this.src); this.$options.listeners = {}; forEach(this.$listeners, (l, name) => { Eif (name === "message" || name === "error") { return; } const cb = (/** @type {MessageEvent} */ e) => this.onEvent(name, e); // @ts-ignore this.$options.listeners[name] = cb; // @ts-ignore this.$options.source.addEventListener(name, cb); }); this.$options.source.onmessage = this.onMessage; this.$options.source.onerror = (/** @type {any} */ err) => { debug("error: %o", err); Iif (hasIn(err, "message")) { this.onError(err); } else Iif (hasIn(err, "data")) { this.onError(new Error(err.data)); } else { this.onError(new Error("[Eventsource]: failed to connect to " + this.src)); } }; }, /** * @param {string} type * @param {MessageEvent} msg */ onEvent(type, msg) { if (this.json) { try { this.$emit(type, JSON.parse(msg.data)); } catch (e) { this.onError(e); } } else { this.$emit(type, msg); } }, /** * @param {MessageEvent} msg */ onMessage(msg) { if (this.json) { try { this.message = JSON.parse(msg.data); this.$emit("message", this.message); } catch (e) { this.onError(e); } } else { this.message = msg.data; this.$emit("message", msg); } } }, /** * @return {Vue.VNode} */ render() { /* render-less component, renders its default slot */ return invoke(this.$scopedSlots, "default", { message: this.message }); } }); export default component; |