UNPKG

ng-tasty

Version:

A lightweight, flexible, and tasty collection of reusable UI components for AngularJS.

149 lines (136 loc) 4.12 kB
/** * @ngdoc service * @name ngTasty.service.webSocket * @description * # webSocket * Factory in ngTasty. */ angular.module('ngTasty.service.webSocket', []) .factory('webSocket', function() { return function(url) { /** * Creates a String[1] representing a binary blob[2] function * containing the WebSocket Factory API. * * [1]: https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL * [2]: https://developer.mozilla.org/en-US/docs/Web/API/Blob * * @return {string} String containing the encoded script */ var blobURL = URL.createObjectURL(new Blob(['(', function() { var WSWorker = (function() { var _ws; /** * Initialize a new WebSocket using * the provided URL parameters. * * @param {string} url The WebSocket URL */ var initialize = function(url) { _ws = new WebSocket(url); }; /** * Listens for any message coming from the WebSocket * and send its content to the main JS thread using postMessage[1]. * * [1]: https://developer.mozilla.org/en-US/docs/Web/API/Worker.postMessage * */ var on = function() { _ws.onmessage = function(response) { var data = JSON.parse(response.data); self.postMessage(data); }; }; /** * Sends data to the WebSocket. * * @param {string} data */ var send = function(data) { _ws.send(data); }; return { initialize: initialize, on: on, send: send }; })(); /** * Listens for incoming messages from the main * JavaScript Thread. * * The commands allowed are: * * ws_new ~> Calls initialize on the Web Socket Worker * ws_on ~> Register the supplied callback * ws_send ~> Sends a message to the underlying WebSocket * encoding it as a string (JSON.stringify) * */ self.addEventListener('message', function(e) { switch (e.data.cmd) { case 'ws_new': WSWorker.initialize(e.data.url); break; case 'ws_on': WSWorker.on(); break; case 'ws_send': WSWorker.send(JSON.stringify(e.data.data)); break; default: console.log('Unknown command: ' + e.data.cmd); } }); }.toString(), ')()'], { type: 'application/javascript' })); // Create a new WebSocket Worker, revoke the URL since // it's not useful anymore. var _worker = new Worker(blobURL); URL.revokeObjectURL(blobURL); // Tell the WebSocket Worker to init a new WebSocket _worker.postMessage({ cmd: 'ws_new', url: url }); return { /** * Registers a callback to a specific Worker event listener. * There are two different events: * * - 'all' ~> subscribes to all websocket messages * - 'type'~> subscribes to all websocket messages containing * a field named 'type'. * * For example, WebSockets Server events like this one: * * { * 'type': 'tweet', * 'data': ... * } * * can be handled in the following way: * * ws.on('twitter', function(data) { * ... * }); * * @param {string} event The event name * @param {Function} cb Callback with output data (first param) */ on: function(event, cb) { _worker.postMessage({ cmd: 'ws_on' }); _worker.addEventListener('message', function(e) { if (event === 'all' || e.data.type === event) { cb(e.data); } }); }, /** * Sends data to the WebSocket. * * @param {Any} data */ send: function(data) { _worker.postMessage({ cmd: 'ws_send', data: data }); } }; }; });