實現跨瀏覽器、跨設備雙向通訊層
class Emitter { _subs: {}; construtor (params?: object) { return(params && this.mixin(params)); } mixin (params) { for (let key in Emitter.prototype) { params[key] = Emitter.prototype[key]; } return params; } on (event, fn) { (this._subs[event] = this._subs[event] || []).push(fn); return this; } once (event, fn) { function on () { this.off(event, fn); fn.apply(this, arguments); } on.fn = fn; this.on(event, on); return this; } off (event, fn) { if (0 === arguments.length) { this._subs = {}; return this; } let callbacks = this._subs[event]; if (!callbacks || !callbacks.length === 0) return this; if (1 === arguments.length) { delete this._subs[event]; return this; } let cb; for (let i = 0; i < callbacks.length; i++) { cb = callbacks[i]; if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1); break; } } return this; } emit (event, ...args?: any) { callbacks = this._subs[event]; callbacks.forEach((item)=>{ item.apply(this.args); }); return this; } }
base class [Transport]web
websocket瀏覽器
class WS extends Transport { name: string = 'websocket'; supportsBinary: boolean = true; constructor (params) { super(params); } doOpen () { const uri = this.uri(); const protocols = this.protocols; let opts = { agent: this.agent } // SSL options for Node.js client opts.pfx = this.pfx; opts.key = this.key; opts.passphrase = this.passphrase; opts.cert = this.cert; opts.ca = this.ca; opts.ciphers = this.ciphers; opts.rejectUnauthorized = this.rejectUnauthorized; if (this.extraHeaders) { opts.headers = this.extraHeaders; } if (this.localAddress) { opts.localAddress = this.localAddress; } try { this.ws = this.usingBrowserWebSocket ? (protocols ? new WebSocket(uri, protocols) : new WebSocket(uri)) : new WebSocket(uri, protocols, opts); } catch (err) { return this.emit('error', err); } this.addEventListeners(); } doClose () { if (typeof this.ws !== 'undefined') { this.ws.close(); } } write () { } addEventListener () { this.ws.onopen = () => { this.onOpen(); } this.ws.onclose = () => { this.onClose(); } this.ws.onmessage = (ev) => { this.onData(ev.data); } this.ws.onerror = () => { this.onError('websocket error', e); } } }