UNPKG

pusher-js

Version:

Pusher JavaScript library for browser, React Native, NodeJS and web workers

142 lines (128 loc) 3.92 kB
import Factory from "../utils/factory"; import Util from '../util'; import * as Errors from '../errors'; import * as Collections from '../utils/collections'; import Strategy from './strategy'; import Transport from '../transports/transport'; import StrategyOptions from './strategy_options'; import Handshake from "../connection/handshake"; /** Provides a strategy interface for transports. * * @param {String} name * @param {Number} priority * @param {Class} transport * @param {Object} options */ export default class TransportStrategy implements Strategy { name: string; priority: number; transport: Transport; options: StrategyOptions; constructor(name : string, priority : number, transport : Transport, options : StrategyOptions) { this.name = name; this.priority = priority; this.transport = transport; this.options = options || {}; } /** Returns whether the transport is supported in the browser. * * @returns {Boolean} */ isSupported() : boolean { return this.transport.isSupported({ encrypted: this.options.encrypted }); } /** Launches a connection attempt and returns a strategy runner. * * @param {Function} callback * @return {Object} strategy runner */ connect(minPriority : number, callback : Function) { if (!this.isSupported()) { return failAttempt(new Errors.UnsupportedStrategy(), callback); } else if (this.priority < minPriority) { return failAttempt(new Errors.TransportPriorityTooLow(), callback); } var connected = false; var transport = this.transport.createConnection( this.name, this.priority, this.options.key, this.options ); var handshake = null; var onInitialized = function() { transport.unbind("initialized", onInitialized); transport.connect(); }; var onOpen = function() { handshake = Factory.createHandshake(transport, function(result) { connected = true; unbindListeners(); callback(null, result); }); }; var onError = function(error) { unbindListeners(); callback(error); }; var onClosed = function() { unbindListeners(); var serializedTransport; // The reason for this try/catch block is that on React Native // the WebSocket object is circular. Therefore transport.socket will // throw errors upon stringification. Collections.safeJSONStringify // discards circular references when serializing. try { serializedTransport = JSON.stringify(transport); } catch (e) { serializedTransport = Collections.safeJSONStringify(transport); } callback(new Errors.TransportClosed(serializedTransport)); }; var unbindListeners = function() { transport.unbind("initialized", onInitialized); transport.unbind("open", onOpen); transport.unbind("error", onError); transport.unbind("closed", onClosed); }; transport.bind("initialized", onInitialized); transport.bind("open", onOpen); transport.bind("error", onError); transport.bind("closed", onClosed); // connect will be called automatically after initialization transport.initialize(); return { abort: ()=> { if (connected) { return; } unbindListeners(); if (handshake) { handshake.close(); } else { transport.close(); } }, forceMinPriority: (p)=> { if (connected) { return; } if (this.priority < p) { if (handshake) { handshake.close(); } else { transport.close(); } } } }; } } function failAttempt(error : Error, callback : Function) { Util.defer(function() { callback(error); }); return { abort: function() {}, forceMinPriority: function() {} }; }