angular-websocket
Advanced tools
Comparing version 1.0.6 to 1.0.7
(function() { | ||
'use strict'; | ||
@@ -26,4 +27,3 @@ function $WebSocketBackend() { | ||
this.createWebSocketBackend = function (url, protocols) { | ||
function createWebSocketBackend(url, protocols) { | ||
pendingConnects.push(url); | ||
@@ -39,3 +39,5 @@ // pendingConnects.push({ | ||
return new $MockWebSocket(url); | ||
}; | ||
} | ||
this.create = createWebSocketBackend; | ||
this.createWebSocketBackend = createWebSocketBackend; | ||
@@ -42,0 +44,0 @@ this.flush = function () { |
(function() { | ||
'use strict'; | ||
var noop = function() {}; | ||
var objectFreeze = (Object.freeze) ? Object.freeze : noop; | ||
var noop = angular.noop; | ||
var objectFreeze = (Object.freeze) ? Object.freeze : noop; | ||
var objectDefineProperty = Object.defineProperty; | ||
var isString = angular.isString; | ||
var isString = angular.isString; | ||
var isFunction = angular.isFunction; | ||
var isDefined = angular.isDefined; | ||
var isDefined = angular.isDefined; | ||
var isObject = angular.isObject; | ||
var isArray = angular.isArray; | ||
var arraySlice = Array.prototype.slice; | ||
var isArray = angular.isArray; | ||
// ie8 wat | ||
@@ -39,12 +40,9 @@ if (!Array.prototype.indexOf) { | ||
fToBind = this, | ||
fNOP = function() {}, | ||
FNOP = function() {}, | ||
fBound = function() { | ||
return fToBind.apply(this instanceof fNOP && oThis | ||
? this | ||
: oThis, | ||
aArgs.concat(arraySlice.call(arguments))); | ||
return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, aArgs.concat(arraySlice.call(arguments))); | ||
}; | ||
fNOP.prototype = this.prototype; | ||
fBound.prototype = new fNOP(); | ||
FNOP.prototype = this.prototype; | ||
fBound.prototype = new FNOP(); | ||
@@ -55,20 +53,14 @@ return fBound; | ||
$WebSocketProvider.$inject = ['$rootScope', '$q', '$timeout', '$websocketBackend']; | ||
// $WebSocketProvider.$inject = ['$rootScope', '$q', '$timeout', '$websocketBackend']; | ||
function $WebSocketProvider($rootScope, $q, $timeout, $websocketBackend) { | ||
function safeDigest(autoApply) { | ||
if (autoApply && !$rootScope.$$phase) { | ||
$rootScope.$apply(); | ||
} | ||
} | ||
function $WebSocket(url, options) { | ||
function $WebSocket(url, protocols, options) { | ||
// var bits = url.split('/'); | ||
var protocols = options && options.protocols; | ||
if (isString(options) || isArray(options)) { | ||
protocols = options; | ||
if (!options && isObject(protocols) && !isArray(protocols)) { | ||
options = protocols; | ||
protocols = undefined; | ||
} | ||
this.protocols = protocols || 'Sec-WebSocket-Protocol'; | ||
this.protocols = protocols; | ||
this.url = url || 'Missing URL'; | ||
@@ -83,10 +75,15 @@ this.ssl = /(wss)/i.test(this.url); | ||
this._reconnectAttempts = 0; | ||
this.initialTimeout = 500; // 500ms | ||
this.maxTimeout = 5 * 60 * 1000; // 5 minutes | ||
this.sendQueue = []; | ||
this.onOpenCallbacks = []; | ||
// TODO: refactor options to use isDefined | ||
this.scope = options && options.scope || $rootScope; | ||
this.rootScopeFailover = options && options.rootScopeFailover && true; | ||
// this.useApplyAsync = options && options.useApplyAsync || false; | ||
this._reconnectAttempts = options && options.reconnectAttempts || 0; | ||
this.initialTimeout = options && options.initialTimeout || 500; // 500ms | ||
this.maxTimeout = options && options.maxTimeout || 5 * 60 * 1000; // 5 minutes | ||
this.sendQueue = []; | ||
this.onOpenCallbacks = []; | ||
this.onMessageCallbacks = []; | ||
this.onErrorCallbacks = []; | ||
this.onCloseCallbacks = []; | ||
this.onErrorCallbacks = []; | ||
this.onCloseCallbacks = []; | ||
@@ -100,2 +97,3 @@ objectFreeze(this._readyStateConstants); | ||
} | ||
} | ||
@@ -115,12 +113,23 @@ | ||
$WebSocket.prototype.close = function (force) { | ||
if (force || !this.socket.bufferedAmount) { | ||
this.socket.close(); | ||
$WebSocket.prototype.safeDigest = function safeDigest(autoApply) { | ||
if (autoApply && !this.scope.$$phase) { | ||
this.scope.$digest(); | ||
} | ||
}; | ||
$WebSocket.prototype.bindToScope = function bindToScope(scope) { | ||
if (scope) { | ||
this.scope = scope; | ||
if (this.rootScopeFailover) { | ||
this.scope.$on('$destroy', function() { | ||
this.scope = $rootScope; | ||
}); | ||
} | ||
} | ||
return this; | ||
}; | ||
$WebSocket.prototype._connect = function (force) { | ||
$WebSocket.prototype._connect = function _connect(force) { | ||
if (force || !this.socket || this.socket.readyState !== this._readyStateConstants.OPEN) { | ||
this.socket = $websocketBackend.createWebSocketBackend(this.url, this.protocols); | ||
this.socket = $websocketBackend.create(this.url, this.protocols); | ||
this.socket.onopen = this._onOpenHandler.bind(this); | ||
@@ -133,3 +142,3 @@ this.socket.onmessage = this._onMessageHandler.bind(this); | ||
$WebSocket.prototype.fireQueue = function () { | ||
$WebSocket.prototype.fireQueue = function fireQueue() { | ||
while (this.sendQueue.length && this.socket.readyState === this._readyStateConstants.OPEN) { | ||
@@ -145,3 +154,3 @@ var data = this.sendQueue.shift(); | ||
$WebSocket.prototype.notifyOpenCallbacks = function () { | ||
$WebSocket.prototype.notifyOpenCallbacks = function notifyOpenCallbacks() { | ||
for (var i = 0; i < this.onOpenCallbacks.length; i++) { | ||
@@ -152,3 +161,3 @@ this.onOpenCallbacks[i].call(this); | ||
$WebSocket.prototype.notifyCloseCallbacks = function (event) { | ||
$WebSocket.prototype.notifyCloseCallbacks = function notifyCloseCallbacks(event) { | ||
for (var i = 0; i < this.onCloseCallbacks.length; i++) { | ||
@@ -158,3 +167,4 @@ this.onCloseCallbacks[i].call(this, event); | ||
}; | ||
$WebSocket.prototype.notifyErrorCallbacks = function (event) { | ||
$WebSocket.prototype.notifyErrorCallbacks = function notifyErrorCallbacks(event) { | ||
for (var i = 0; i < this.onErrorCallbacks.length; i++) { | ||
@@ -165,3 +175,3 @@ this.onErrorCallbacks[i].call(this, event); | ||
$WebSocket.prototype.onOpen = function (cb) { | ||
$WebSocket.prototype.onOpen = function onOpen(cb) { | ||
this.onOpenCallbacks.push(cb); | ||
@@ -171,3 +181,3 @@ return this; | ||
$WebSocket.prototype.onClose = function (cb) { | ||
$WebSocket.prototype.onClose = function onClose(cb) { | ||
this.onCloseCallbacks.push(cb); | ||
@@ -177,3 +187,3 @@ return this; | ||
$WebSocket.prototype.onError = function (cb) { | ||
$WebSocket.prototype.onError = function onError(cb) { | ||
this.onErrorCallbacks.push(cb); | ||
@@ -184,3 +194,3 @@ return this; | ||
$WebSocket.prototype.onMessage = function (callback, options) { | ||
$WebSocket.prototype.onMessage = function onMessage(callback, options) { | ||
if (!isFunction(callback)) { | ||
@@ -202,3 +212,3 @@ throw new Error('Callback must be a function'); | ||
$WebSocket.prototype._onOpenHandler = function () { | ||
$WebSocket.prototype._onOpenHandler = function _onOpenHandler() { | ||
this._reconnectAttempts = 0; | ||
@@ -209,3 +219,3 @@ this.notifyOpenCallbacks(); | ||
$WebSocket.prototype._onCloseHandler = function (event) { | ||
$WebSocket.prototype._onCloseHandler = function _onCloseHandler(event) { | ||
this.notifyCloseCallbacks(event); | ||
@@ -217,26 +227,26 @@ if (this._reconnectableStatusCodes.indexOf(event.code) > -1) { | ||
$WebSocket.prototype._onErrorHandler = function (event) { | ||
$WebSocket.prototype._onErrorHandler = function _onErrorHandler(event) { | ||
this.notifyErrorCallbacks(event); | ||
}; | ||
$WebSocket.prototype._onMessageHandler = function (message) { | ||
$WebSocket.prototype._onMessageHandler = function _onMessageHandler(message) { | ||
var pattern; | ||
var socket = this; | ||
var socketInstance = this; | ||
var currentCallback; | ||
for (var i = 0; i < socket.onMessageCallbacks.length; i++) { | ||
currentCallback = socket.onMessageCallbacks[i]; | ||
for (var i = 0; i < socketInstance.onMessageCallbacks.length; i++) { | ||
currentCallback = socketInstance.onMessageCallbacks[i]; | ||
pattern = currentCallback.pattern; | ||
if (pattern) { | ||
if (isString(pattern) && message.data === pattern) { | ||
currentCallback.fn.call(this, message); | ||
safeDigest(currentCallback.autoApply); | ||
currentCallback.fn.call(socketInstance, message); | ||
socketInstance.safeDigest(currentCallback.autoApply); | ||
} | ||
else if (pattern instanceof RegExp && pattern.exec(message.data)) { | ||
currentCallback.fn.call(this, message); | ||
safeDigest(currentCallback.autoApply); | ||
currentCallback.fn.call(socketInstance, message); | ||
socketInstance.safeDigest(currentCallback.autoApply); | ||
} | ||
} | ||
else { | ||
currentCallback.fn.call(this, message); | ||
safeDigest(currentCallback.autoApply); | ||
currentCallback.fn.call(socketInstance, message); | ||
socketInstance.safeDigest(currentCallback.autoApply); | ||
} | ||
@@ -246,16 +256,23 @@ } | ||
$WebSocket.prototype.send = function (data) { | ||
$WebSocket.prototype.close = function close(force) { | ||
if (force || !this.socket.bufferedAmount) { | ||
this.socket.close(); | ||
} | ||
return this; | ||
}; | ||
$WebSocket.prototype.send = function send(data) { | ||
var deferred = $q.defer(); | ||
var socket = this; | ||
var socketInstance = this; | ||
var promise = cancelableify(deferred.promise); | ||
if (socket.readyState === socket._readyStateConstants.RECONNECT_ABORTED) { | ||
if (socketInstance.readyState === socketInstance._readyStateConstants.RECONNECT_ABORTED) { | ||
deferred.reject('Socket connection has been closed'); | ||
} | ||
else { | ||
this.sendQueue.push({ | ||
socketInstance.sendQueue.push({ | ||
message: data, | ||
deferred: deferred | ||
}); | ||
this.fireQueue(); | ||
socketInstance.fireQueue(); | ||
} | ||
@@ -275,5 +292,5 @@ | ||
function cancel(reason) { | ||
socket.sendQueue.splice(socket.sendQueue.indexOf(data), 1); | ||
socketInstance.sendQueue.splice(socketInstance.sendQueue.indexOf(data), 1); | ||
deferred.reject(reason); | ||
return this; | ||
return socketInstance; | ||
} | ||
@@ -284,13 +301,13 @@ | ||
$WebSocket.prototype.reconnect = function () { | ||
this.close(); | ||
$timeout(angular.bind(this, function() { | ||
this._connect(); | ||
}), this._getBackoffDelay(++this._reconnectAttempts), true); | ||
$WebSocket.prototype.reconnect = function reconnect() { | ||
var socketInstance = this; | ||
socketInstance.close(); | ||
return this; | ||
$timeout(socketInstance._connect, socketInstance._getBackoffDelay(++socketInstance._reconnectAttempts)); | ||
return socketInstance; | ||
}; | ||
// Exponential Backoff Formula by Prof. Douglas Thain | ||
// http://dthain.blogspot.co.uk/2009/02/exponential-backoff-in-distributed.html | ||
$WebSocket.prototype._getBackoffDelay = function(attempt) { | ||
$WebSocket.prototype._getBackoffDelay = function _getBackoffDelay(attempt) { | ||
var R = Math.random() + 1; | ||
@@ -305,3 +322,3 @@ var T = this.initialTimeout; | ||
$WebSocket.prototype._setInternalState = function(state) { | ||
$WebSocket.prototype._setInternalState = function _setInternalState(state) { | ||
if (Math.floor(state) !== state || state < 0 || state > 4) { | ||
@@ -323,2 +340,3 @@ throw new Error('state must be an integer between 0 and 4, got: ' + state); | ||
// Read only .readyState | ||
if (objectDefineProperty) { | ||
@@ -340,5 +358,5 @@ objectDefineProperty($WebSocket.prototype, 'readyState', { | ||
$WebSocketBackend.$inject = ['$window']; | ||
function $WebSocketBackend($window) { | ||
this.createWebSocketBackend = function (url, protocols) { | ||
// $WebSocketBackendProvider.$inject = ['$window']; | ||
function $WebSocketBackendProvider($window, $log) { | ||
this.create = function create(url, protocols) { | ||
var match = /wss?:\/\//.exec(url); | ||
@@ -349,2 +367,4 @@ var Socket, ws; | ||
} | ||
// CommonJS | ||
if (typeof exports === 'object' && require) { | ||
@@ -356,2 +376,4 @@ try { | ||
} | ||
// Browser | ||
Socket = Socket || $window.WebSocket || $window.MozWebSocket; | ||
@@ -362,11 +384,16 @@ | ||
} | ||
return new Socket(url); | ||
}; | ||
this.createWebSocketBackend = function createWebSocketBackend(url, protocols) { | ||
$log.warn('Deprecated: Please use .create(url, protocols)'); | ||
return this.create(url, protocols); | ||
}; | ||
} | ||
angular.module('ngWebSocket', []) | ||
.factory('$websocket', $WebSocketProvider) | ||
.factory('WebSocket', $WebSocketProvider) | ||
.service('$websocketBackend', $WebSocketBackend) | ||
.service('WebSocketBackend', $WebSocketBackend); | ||
.factory('$websocket', ['$rootScope', '$q', '$timeout', '$websocketBackend', $WebSocketProvider]) | ||
.factory('WebSocket', ['$rootScope', '$q', '$timeout', 'WebsocketBackend', $WebSocketProvider]) | ||
.service('$websocketBackend', ['$window', '$log', $WebSocketBackendProvider]) | ||
.service('WebSocketBackend', ['$window', '$log', $WebSocketBackendProvider]); | ||
@@ -373,0 +400,0 @@ |
@@ -1,2 +0,2 @@ | ||
!function(){"use strict";function t(t,e,n,c){function h(e){e&&!t.$$phase&&t.$apply()}function u(t,e){var n=e&&e.protocols;(s(e)||l(e))&&(n=e),this.protocols=n||"Sec-WebSocket-Protocol",this.url=t||"Missing URL",this.ssl=/(wss)/i.test(this.url),this._reconnectAttempts=0,this.initialTimeout=500,this.maxTimeout=3e5,this.sendQueue=[],this.onOpenCallbacks=[],this.onMessageCallbacks=[],this.onErrorCallbacks=[],this.onCloseCallbacks=[],o(this._readyStateConstants),t?this._connect():this._setInternalState(0)}return u.prototype._readyStateConstants={CONNECTING:0,OPEN:1,CLOSING:2,CLOSED:3,RECONNECT_ABORTED:4},u.prototype._reconnectableStatusCodes=[4e3],u.prototype.close=function(t){return(t||!this.socket.bufferedAmount)&&this.socket.close(),this},u.prototype._connect=function(t){(t||!this.socket||this.socket.readyState!==this._readyStateConstants.OPEN)&&(this.socket=c.createWebSocketBackend(this.url,this.protocols),this.socket.onopen=this._onOpenHandler.bind(this),this.socket.onmessage=this._onMessageHandler.bind(this),this.socket.onerror=this._onErrorHandler.bind(this),this.socket.onclose=this._onCloseHandler.bind(this))},u.prototype.fireQueue=function(){for(;this.sendQueue.length&&this.socket.readyState===this._readyStateConstants.OPEN;){var t=this.sendQueue.shift();this.socket.send(s(t.message)?t.message:JSON.stringify(t.message)),t.deferred.resolve()}},u.prototype.notifyOpenCallbacks=function(){for(var t=0;t<this.onOpenCallbacks.length;t++)this.onOpenCallbacks[t].call(this)},u.prototype.notifyCloseCallbacks=function(t){for(var e=0;e<this.onCloseCallbacks.length;e++)this.onCloseCallbacks[e].call(this,t)},u.prototype.notifyErrorCallbacks=function(t){for(var e=0;e<this.onErrorCallbacks.length;e++)this.onErrorCallbacks[e].call(this,t)},u.prototype.onOpen=function(t){return this.onOpenCallbacks.push(t),this},u.prototype.onClose=function(t){return this.onCloseCallbacks.push(t),this},u.prototype.onError=function(t){return this.onErrorCallbacks.push(t),this},u.prototype.onMessage=function(t,e){if(!i(t))throw new Error("Callback must be a function");if(e&&a(e.filter)&&!s(e.filter)&&!(e.filter instanceof RegExp))throw new Error("Pattern must be a string or regular expression");return this.onMessageCallbacks.push({fn:t,pattern:e?e.filter:void 0,autoApply:e?e.autoApply:!0}),this},u.prototype._onOpenHandler=function(){this._reconnectAttempts=0,this.notifyOpenCallbacks(),this.fireQueue()},u.prototype._onCloseHandler=function(t){this.notifyCloseCallbacks(t),this._reconnectableStatusCodes.indexOf(t.code)>-1&&this.reconnect()},u.prototype._onErrorHandler=function(t){this.notifyErrorCallbacks(t)},u.prototype._onMessageHandler=function(t){for(var e,n,o=this,r=0;r<o.onMessageCallbacks.length;r++)n=o.onMessageCallbacks[r],e=n.pattern,e?s(e)&&t.data===e?(n.fn.call(this,t),h(n.autoApply)):e instanceof RegExp&&e.exec(t.data)&&(n.fn.call(this,t),h(n.autoApply)):(n.fn.call(this,t),h(n.autoApply))},u.prototype.send=function(t){function n(t){t.cancel=o;var e=t.then;return t.then=function(){var t=e.apply(this,arguments);return n(t)},t}function o(e){return s.sendQueue.splice(s.sendQueue.indexOf(t),1),r.reject(e),this}var r=e.defer(),s=this,i=n(r.promise);return s.readyState===s._readyStateConstants.RECONNECT_ABORTED?r.reject("Socket connection has been closed"):(this.sendQueue.push({message:t,deferred:r}),this.fireQueue()),i},u.prototype.reconnect=function(){return this.close(),n(angular.bind(this,function(){this._connect()}),this._getBackoffDelay(++this._reconnectAttempts),!0),this},u.prototype._getBackoffDelay=function(t){var e=Math.random()+1,n=this.initialTimeout,o=2,r=t,s=this.maxTimeout;return Math.floor(Math.min(e*n*Math.pow(o,r),s))},u.prototype._setInternalState=function(t){if(Math.floor(t)!==t||0>t||t>4)throw new Error("state must be an integer between 0 and 4, got: "+t);r||(this.readyState=t||this.socket.readyState),this._internalConnectionState=t,angular.forEach(this.sendQueue,function(t){t.deferred.reject("Message cancelled due to closed socket connection")})},r&&r(u.prototype,"readyState",{get:function(){return this._internalConnectionState||this.socket.readyState},set:function(){throw new Error("The readyState property is read-only")}}),function(t,e){return new u(t,e)}}function e(t){this.createWebSocketBackend=function(e,n){var o,r,s=/wss?:\/\//.exec(e);if(!s)throw new Error("Invalid url provided");if("object"==typeof exports&&require)try{r=require("ws"),o=r.Client||r.client||r}catch(i){}return o=o||t.WebSocket||t.MozWebSocket,n?new o(e,n):new o(e)}}var n=function(){},o=Object.freeze?Object.freeze:n,r=Object.defineProperty,s=angular.isString,i=angular.isFunction,a=angular.isDefined,c=Array.prototype.slice,l=angular.isArray;Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var e=this.length>>>0,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=e);e>n;n++)if(n in this&&this[n]===t)return n;return-1}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=c.call(arguments,1),n=this,o=function(){},r=function(){return n.apply(this instanceof o&&t?this:t,e.concat(c.call(arguments)))};return o.prototype=this.prototype,r.prototype=new o,r}),t.$inject=["$rootScope","$q","$timeout","$websocketBackend"],e.$inject=["$window"],angular.module("ngWebSocket",[]).factory("$websocket",t).factory("WebSocket",t).service("$websocketBackend",e).service("WebSocketBackend",e),angular.module("angular-websocket",["ngWebSocket"])}(); | ||
!function(){"use strict";function t(t,e,o,u){function p(e,o,r){r||!c(o)||l(o)||(r=o,o=void 0),this.protocols=o,this.url=e||"Missing URL",this.ssl=/(wss)/i.test(this.url),this.scope=r&&r.scope||t,this.rootScopeFailover=r&&r.rootScopeFailover&&!0,this._reconnectAttempts=r&&r.reconnectAttempts||0,this.initialTimeout=r&&r.initialTimeout||500,this.maxTimeout=r&&r.maxTimeout||3e5,this.sendQueue=[],this.onOpenCallbacks=[],this.onMessageCallbacks=[],this.onErrorCallbacks=[],this.onCloseCallbacks=[],n(this._readyStateConstants),e?this._connect():this._setInternalState(0)}return p.prototype._readyStateConstants={CONNECTING:0,OPEN:1,CLOSING:2,CLOSED:3,RECONNECT_ABORTED:4},p.prototype._reconnectableStatusCodes=[4e3],p.prototype.safeDigest=function(t){t&&!this.scope.$$phase&&this.scope.$digest()},p.prototype.bindToScope=function(e){return e&&(this.scope=e,this.rootScopeFailover&&this.scope.$on("$destroy",function(){this.scope=t})),this},p.prototype._connect=function(t){(t||!this.socket||this.socket.readyState!==this._readyStateConstants.OPEN)&&(this.socket=u.create(this.url,this.protocols),this.socket.onopen=this._onOpenHandler.bind(this),this.socket.onmessage=this._onMessageHandler.bind(this),this.socket.onerror=this._onErrorHandler.bind(this),this.socket.onclose=this._onCloseHandler.bind(this))},p.prototype.fireQueue=function(){for(;this.sendQueue.length&&this.socket.readyState===this._readyStateConstants.OPEN;){var t=this.sendQueue.shift();this.socket.send(s(t.message)?t.message:JSON.stringify(t.message)),t.deferred.resolve()}},p.prototype.notifyOpenCallbacks=function(){for(var t=0;t<this.onOpenCallbacks.length;t++)this.onOpenCallbacks[t].call(this)},p.prototype.notifyCloseCallbacks=function(t){for(var e=0;e<this.onCloseCallbacks.length;e++)this.onCloseCallbacks[e].call(this,t)},p.prototype.notifyErrorCallbacks=function(t){for(var e=0;e<this.onErrorCallbacks.length;e++)this.onErrorCallbacks[e].call(this,t)},p.prototype.onOpen=function(t){return this.onOpenCallbacks.push(t),this},p.prototype.onClose=function(t){return this.onCloseCallbacks.push(t),this},p.prototype.onError=function(t){return this.onErrorCallbacks.push(t),this},p.prototype.onMessage=function(t,e){if(!i(t))throw new Error("Callback must be a function");if(e&&a(e.filter)&&!s(e.filter)&&!(e.filter instanceof RegExp))throw new Error("Pattern must be a string or regular expression");return this.onMessageCallbacks.push({fn:t,pattern:e?e.filter:void 0,autoApply:e?e.autoApply:!0}),this},p.prototype._onOpenHandler=function(){this._reconnectAttempts=0,this.notifyOpenCallbacks(),this.fireQueue()},p.prototype._onCloseHandler=function(t){this.notifyCloseCallbacks(t),this._reconnectableStatusCodes.indexOf(t.code)>-1&&this.reconnect()},p.prototype._onErrorHandler=function(t){this.notifyErrorCallbacks(t)},p.prototype._onMessageHandler=function(t){for(var e,o,n=this,r=0;r<n.onMessageCallbacks.length;r++)o=n.onMessageCallbacks[r],e=o.pattern,e?s(e)&&t.data===e?(o.fn.call(n,t),n.safeDigest(o.autoApply)):e instanceof RegExp&&e.exec(t.data)&&(o.fn.call(n,t),n.safeDigest(o.autoApply)):(o.fn.call(n,t),n.safeDigest(o.autoApply))},p.prototype.close=function(t){return(t||!this.socket.bufferedAmount)&&this.socket.close(),this},p.prototype.send=function(t){function o(t){t.cancel=n;var e=t.then;return t.then=function(){var t=e.apply(this,arguments);return o(t)},t}function n(e){return s.sendQueue.splice(s.sendQueue.indexOf(t),1),r.reject(e),s}var r=e.defer(),s=this,i=o(r.promise);return s.readyState===s._readyStateConstants.RECONNECT_ABORTED?r.reject("Socket connection has been closed"):(s.sendQueue.push({message:t,deferred:r}),s.fireQueue()),i},p.prototype.reconnect=function(){var t=this;return t.close(),o(t._connect,t._getBackoffDelay(++t._reconnectAttempts)),t},p.prototype._getBackoffDelay=function(t){var e=Math.random()+1,o=this.initialTimeout,n=2,r=t,s=this.maxTimeout;return Math.floor(Math.min(e*o*Math.pow(n,r),s))},p.prototype._setInternalState=function(t){if(Math.floor(t)!==t||0>t||t>4)throw new Error("state must be an integer between 0 and 4, got: "+t);r||(this.readyState=t||this.socket.readyState),this._internalConnectionState=t,angular.forEach(this.sendQueue,function(t){t.deferred.reject("Message cancelled due to closed socket connection")})},r&&r(p.prototype,"readyState",{get:function(){return this._internalConnectionState||this.socket.readyState},set:function(){throw new Error("The readyState property is read-only")}}),function(t,e){return new p(t,e)}}function e(t,e){this.create=function(e,o){var n,r,s=/wss?:\/\//.exec(e);if(!s)throw new Error("Invalid url provided");if("object"==typeof exports&&require)try{r=require("ws"),n=r.Client||r.client||r}catch(i){}return n=n||t.WebSocket||t.MozWebSocket,o?new n(e,o):new n(e)},this.createWebSocketBackend=function(t,o){return e.warn("Deprecated: Please use .create(url, protocols)"),this.create(t,o)}}var o=angular.noop,n=Object.freeze?Object.freeze:o,r=Object.defineProperty,s=angular.isString,i=angular.isFunction,a=angular.isDefined,c=angular.isObject,l=angular.isArray,u=Array.prototype.slice;Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var e=this.length>>>0,o=Number(arguments[1])||0;for(o=0>o?Math.ceil(o):Math.floor(o),0>o&&(o+=e);e>o;o++)if(o in this&&this[o]===t)return o;return-1}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=u.call(arguments,1),o=this,n=function(){},r=function(){return o.apply(this instanceof n&&t?this:t,e.concat(u.call(arguments)))};return n.prototype=this.prototype,r.prototype=new n,r}),angular.module("ngWebSocket",[]).factory("$websocket",["$rootScope","$q","$timeout","$websocketBackend",t]).factory("WebSocket",["$rootScope","$q","$timeout","WebsocketBackend",t]).service("$websocketBackend",["$window","$log",e]).service("WebSocketBackend",["$window","$log",e]),angular.module("angular-websocket",["ngWebSocket"])}(); | ||
//# sourceMappingURL=angular-websocket.min.js.map |
@@ -0,1 +1,13 @@ | ||
## 1.0.7 (2015-1-20) | ||
Features: | ||
- Named functions for debugging | ||
- Add .bindToScope() and expose .safeDigest() with scope/rootScopeFailover option | ||
Bugfixes: | ||
- Remove default protocol | ||
Deprecated: | ||
- Change $WebSocketBackend.createWebSocketBackend -> $WebSocketBackend.create | ||
## 1.0.6 (2015-1-7) | ||
@@ -2,0 +14,0 @@ |
(function() { | ||
'use strict'; | ||
@@ -26,4 +27,3 @@ function $WebSocketBackend() { | ||
this.createWebSocketBackend = function (url, protocols) { | ||
function createWebSocketBackend(url, protocols) { | ||
pendingConnects.push(url); | ||
@@ -39,3 +39,5 @@ // pendingConnects.push({ | ||
return new $MockWebSocket(url); | ||
}; | ||
} | ||
this.create = createWebSocketBackend; | ||
this.createWebSocketBackend = createWebSocketBackend; | ||
@@ -42,0 +44,0 @@ this.flush = function () { |
(function() { | ||
'use strict'; | ||
var noop = function() {}; | ||
var objectFreeze = (Object.freeze) ? Object.freeze : noop; | ||
var noop = angular.noop; | ||
var objectFreeze = (Object.freeze) ? Object.freeze : noop; | ||
var objectDefineProperty = Object.defineProperty; | ||
var isString = angular.isString; | ||
var isString = angular.isString; | ||
var isFunction = angular.isFunction; | ||
var isDefined = angular.isDefined; | ||
var isDefined = angular.isDefined; | ||
var isObject = angular.isObject; | ||
var isArray = angular.isArray; | ||
var arraySlice = Array.prototype.slice; | ||
var isArray = angular.isArray; | ||
// ie8 wat | ||
@@ -39,12 +40,9 @@ if (!Array.prototype.indexOf) { | ||
fToBind = this, | ||
fNOP = function() {}, | ||
FNOP = function() {}, | ||
fBound = function() { | ||
return fToBind.apply(this instanceof fNOP && oThis | ||
? this | ||
: oThis, | ||
aArgs.concat(arraySlice.call(arguments))); | ||
return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, aArgs.concat(arraySlice.call(arguments))); | ||
}; | ||
fNOP.prototype = this.prototype; | ||
fBound.prototype = new fNOP(); | ||
FNOP.prototype = this.prototype; | ||
fBound.prototype = new FNOP(); | ||
@@ -55,20 +53,14 @@ return fBound; | ||
$WebSocketProvider.$inject = ['$rootScope', '$q', '$timeout', '$websocketBackend']; | ||
// $WebSocketProvider.$inject = ['$rootScope', '$q', '$timeout', '$websocketBackend']; | ||
function $WebSocketProvider($rootScope, $q, $timeout, $websocketBackend) { | ||
function safeDigest(autoApply) { | ||
if (autoApply && !$rootScope.$$phase) { | ||
$rootScope.$apply(); | ||
} | ||
} | ||
function $WebSocket(url, options) { | ||
function $WebSocket(url, protocols, options) { | ||
// var bits = url.split('/'); | ||
var protocols = options && options.protocols; | ||
if (isString(options) || isArray(options)) { | ||
protocols = options; | ||
if (!options && isObject(protocols) && !isArray(protocols)) { | ||
options = protocols; | ||
protocols = undefined; | ||
} | ||
this.protocols = protocols || 'Sec-WebSocket-Protocol'; | ||
this.protocols = protocols; | ||
this.url = url || 'Missing URL'; | ||
@@ -83,10 +75,15 @@ this.ssl = /(wss)/i.test(this.url); | ||
this._reconnectAttempts = 0; | ||
this.initialTimeout = 500; // 500ms | ||
this.maxTimeout = 5 * 60 * 1000; // 5 minutes | ||
this.sendQueue = []; | ||
this.onOpenCallbacks = []; | ||
// TODO: refactor options to use isDefined | ||
this.scope = options && options.scope || $rootScope; | ||
this.rootScopeFailover = options && options.rootScopeFailover && true; | ||
// this.useApplyAsync = options && options.useApplyAsync || false; | ||
this._reconnectAttempts = options && options.reconnectAttempts || 0; | ||
this.initialTimeout = options && options.initialTimeout || 500; // 500ms | ||
this.maxTimeout = options && options.maxTimeout || 5 * 60 * 1000; // 5 minutes | ||
this.sendQueue = []; | ||
this.onOpenCallbacks = []; | ||
this.onMessageCallbacks = []; | ||
this.onErrorCallbacks = []; | ||
this.onCloseCallbacks = []; | ||
this.onErrorCallbacks = []; | ||
this.onCloseCallbacks = []; | ||
@@ -100,2 +97,3 @@ objectFreeze(this._readyStateConstants); | ||
} | ||
} | ||
@@ -115,12 +113,23 @@ | ||
$WebSocket.prototype.close = function (force) { | ||
if (force || !this.socket.bufferedAmount) { | ||
this.socket.close(); | ||
$WebSocket.prototype.safeDigest = function safeDigest(autoApply) { | ||
if (autoApply && !this.scope.$$phase) { | ||
this.scope.$digest(); | ||
} | ||
}; | ||
$WebSocket.prototype.bindToScope = function bindToScope(scope) { | ||
if (scope) { | ||
this.scope = scope; | ||
if (this.rootScopeFailover) { | ||
this.scope.$on('$destroy', function() { | ||
this.scope = $rootScope; | ||
}); | ||
} | ||
} | ||
return this; | ||
}; | ||
$WebSocket.prototype._connect = function (force) { | ||
$WebSocket.prototype._connect = function _connect(force) { | ||
if (force || !this.socket || this.socket.readyState !== this._readyStateConstants.OPEN) { | ||
this.socket = $websocketBackend.createWebSocketBackend(this.url, this.protocols); | ||
this.socket = $websocketBackend.create(this.url, this.protocols); | ||
this.socket.onopen = this._onOpenHandler.bind(this); | ||
@@ -133,3 +142,3 @@ this.socket.onmessage = this._onMessageHandler.bind(this); | ||
$WebSocket.prototype.fireQueue = function () { | ||
$WebSocket.prototype.fireQueue = function fireQueue() { | ||
while (this.sendQueue.length && this.socket.readyState === this._readyStateConstants.OPEN) { | ||
@@ -145,3 +154,3 @@ var data = this.sendQueue.shift(); | ||
$WebSocket.prototype.notifyOpenCallbacks = function () { | ||
$WebSocket.prototype.notifyOpenCallbacks = function notifyOpenCallbacks() { | ||
for (var i = 0; i < this.onOpenCallbacks.length; i++) { | ||
@@ -152,3 +161,3 @@ this.onOpenCallbacks[i].call(this); | ||
$WebSocket.prototype.notifyCloseCallbacks = function (event) { | ||
$WebSocket.prototype.notifyCloseCallbacks = function notifyCloseCallbacks(event) { | ||
for (var i = 0; i < this.onCloseCallbacks.length; i++) { | ||
@@ -158,3 +167,4 @@ this.onCloseCallbacks[i].call(this, event); | ||
}; | ||
$WebSocket.prototype.notifyErrorCallbacks = function (event) { | ||
$WebSocket.prototype.notifyErrorCallbacks = function notifyErrorCallbacks(event) { | ||
for (var i = 0; i < this.onErrorCallbacks.length; i++) { | ||
@@ -165,3 +175,3 @@ this.onErrorCallbacks[i].call(this, event); | ||
$WebSocket.prototype.onOpen = function (cb) { | ||
$WebSocket.prototype.onOpen = function onOpen(cb) { | ||
this.onOpenCallbacks.push(cb); | ||
@@ -171,3 +181,3 @@ return this; | ||
$WebSocket.prototype.onClose = function (cb) { | ||
$WebSocket.prototype.onClose = function onClose(cb) { | ||
this.onCloseCallbacks.push(cb); | ||
@@ -177,3 +187,3 @@ return this; | ||
$WebSocket.prototype.onError = function (cb) { | ||
$WebSocket.prototype.onError = function onError(cb) { | ||
this.onErrorCallbacks.push(cb); | ||
@@ -184,3 +194,3 @@ return this; | ||
$WebSocket.prototype.onMessage = function (callback, options) { | ||
$WebSocket.prototype.onMessage = function onMessage(callback, options) { | ||
if (!isFunction(callback)) { | ||
@@ -202,3 +212,3 @@ throw new Error('Callback must be a function'); | ||
$WebSocket.prototype._onOpenHandler = function () { | ||
$WebSocket.prototype._onOpenHandler = function _onOpenHandler() { | ||
this._reconnectAttempts = 0; | ||
@@ -209,3 +219,3 @@ this.notifyOpenCallbacks(); | ||
$WebSocket.prototype._onCloseHandler = function (event) { | ||
$WebSocket.prototype._onCloseHandler = function _onCloseHandler(event) { | ||
this.notifyCloseCallbacks(event); | ||
@@ -217,26 +227,26 @@ if (this._reconnectableStatusCodes.indexOf(event.code) > -1) { | ||
$WebSocket.prototype._onErrorHandler = function (event) { | ||
$WebSocket.prototype._onErrorHandler = function _onErrorHandler(event) { | ||
this.notifyErrorCallbacks(event); | ||
}; | ||
$WebSocket.prototype._onMessageHandler = function (message) { | ||
$WebSocket.prototype._onMessageHandler = function _onMessageHandler(message) { | ||
var pattern; | ||
var socket = this; | ||
var socketInstance = this; | ||
var currentCallback; | ||
for (var i = 0; i < socket.onMessageCallbacks.length; i++) { | ||
currentCallback = socket.onMessageCallbacks[i]; | ||
for (var i = 0; i < socketInstance.onMessageCallbacks.length; i++) { | ||
currentCallback = socketInstance.onMessageCallbacks[i]; | ||
pattern = currentCallback.pattern; | ||
if (pattern) { | ||
if (isString(pattern) && message.data === pattern) { | ||
currentCallback.fn.call(this, message); | ||
safeDigest(currentCallback.autoApply); | ||
currentCallback.fn.call(socketInstance, message); | ||
socketInstance.safeDigest(currentCallback.autoApply); | ||
} | ||
else if (pattern instanceof RegExp && pattern.exec(message.data)) { | ||
currentCallback.fn.call(this, message); | ||
safeDigest(currentCallback.autoApply); | ||
currentCallback.fn.call(socketInstance, message); | ||
socketInstance.safeDigest(currentCallback.autoApply); | ||
} | ||
} | ||
else { | ||
currentCallback.fn.call(this, message); | ||
safeDigest(currentCallback.autoApply); | ||
currentCallback.fn.call(socketInstance, message); | ||
socketInstance.safeDigest(currentCallback.autoApply); | ||
} | ||
@@ -246,16 +256,23 @@ } | ||
$WebSocket.prototype.send = function (data) { | ||
$WebSocket.prototype.close = function close(force) { | ||
if (force || !this.socket.bufferedAmount) { | ||
this.socket.close(); | ||
} | ||
return this; | ||
}; | ||
$WebSocket.prototype.send = function send(data) { | ||
var deferred = $q.defer(); | ||
var socket = this; | ||
var socketInstance = this; | ||
var promise = cancelableify(deferred.promise); | ||
if (socket.readyState === socket._readyStateConstants.RECONNECT_ABORTED) { | ||
if (socketInstance.readyState === socketInstance._readyStateConstants.RECONNECT_ABORTED) { | ||
deferred.reject('Socket connection has been closed'); | ||
} | ||
else { | ||
this.sendQueue.push({ | ||
socketInstance.sendQueue.push({ | ||
message: data, | ||
deferred: deferred | ||
}); | ||
this.fireQueue(); | ||
socketInstance.fireQueue(); | ||
} | ||
@@ -275,5 +292,5 @@ | ||
function cancel(reason) { | ||
socket.sendQueue.splice(socket.sendQueue.indexOf(data), 1); | ||
socketInstance.sendQueue.splice(socketInstance.sendQueue.indexOf(data), 1); | ||
deferred.reject(reason); | ||
return this; | ||
return socketInstance; | ||
} | ||
@@ -284,13 +301,13 @@ | ||
$WebSocket.prototype.reconnect = function () { | ||
this.close(); | ||
$timeout(angular.bind(this, function() { | ||
this._connect(); | ||
}), this._getBackoffDelay(++this._reconnectAttempts), true); | ||
$WebSocket.prototype.reconnect = function reconnect() { | ||
var socketInstance = this; | ||
socketInstance.close(); | ||
return this; | ||
$timeout(socketInstance._connect, socketInstance._getBackoffDelay(++socketInstance._reconnectAttempts)); | ||
return socketInstance; | ||
}; | ||
// Exponential Backoff Formula by Prof. Douglas Thain | ||
// http://dthain.blogspot.co.uk/2009/02/exponential-backoff-in-distributed.html | ||
$WebSocket.prototype._getBackoffDelay = function(attempt) { | ||
$WebSocket.prototype._getBackoffDelay = function _getBackoffDelay(attempt) { | ||
var R = Math.random() + 1; | ||
@@ -305,3 +322,3 @@ var T = this.initialTimeout; | ||
$WebSocket.prototype._setInternalState = function(state) { | ||
$WebSocket.prototype._setInternalState = function _setInternalState(state) { | ||
if (Math.floor(state) !== state || state < 0 || state > 4) { | ||
@@ -323,2 +340,3 @@ throw new Error('state must be an integer between 0 and 4, got: ' + state); | ||
// Read only .readyState | ||
if (objectDefineProperty) { | ||
@@ -340,5 +358,5 @@ objectDefineProperty($WebSocket.prototype, 'readyState', { | ||
$WebSocketBackend.$inject = ['$window']; | ||
function $WebSocketBackend($window) { | ||
this.createWebSocketBackend = function (url, protocols) { | ||
// $WebSocketBackendProvider.$inject = ['$window']; | ||
function $WebSocketBackendProvider($window, $log) { | ||
this.create = function create(url, protocols) { | ||
var match = /wss?:\/\//.exec(url); | ||
@@ -349,2 +367,4 @@ var Socket, ws; | ||
} | ||
// CommonJS | ||
if (typeof exports === 'object' && require) { | ||
@@ -356,2 +376,4 @@ try { | ||
} | ||
// Browser | ||
Socket = Socket || $window.WebSocket || $window.MozWebSocket; | ||
@@ -362,11 +384,16 @@ | ||
} | ||
return new Socket(url); | ||
}; | ||
this.createWebSocketBackend = function createWebSocketBackend(url, protocols) { | ||
$log.warn('Deprecated: Please use .create(url, protocols)'); | ||
return this.create(url, protocols); | ||
}; | ||
} | ||
angular.module('ngWebSocket', []) | ||
.factory('$websocket', $WebSocketProvider) | ||
.factory('WebSocket', $WebSocketProvider) | ||
.service('$websocketBackend', $WebSocketBackend) | ||
.service('WebSocketBackend', $WebSocketBackend); | ||
.factory('$websocket', ['$rootScope', '$q', '$timeout', '$websocketBackend', $WebSocketProvider]) | ||
.factory('WebSocket', ['$rootScope', '$q', '$timeout', 'WebsocketBackend', $WebSocketProvider]) | ||
.service('$websocketBackend', ['$window', '$log', $WebSocketBackendProvider]) | ||
.service('WebSocketBackend', ['$window', '$log', $WebSocketBackendProvider]); | ||
@@ -373,0 +400,0 @@ |
@@ -1,2 +0,2 @@ | ||
!function(){"use strict";function t(t,e,n,c){function h(e){e&&!t.$$phase&&t.$apply()}function u(t,e){var n=e&&e.protocols;(s(e)||l(e))&&(n=e),this.protocols=n||"Sec-WebSocket-Protocol",this.url=t||"Missing URL",this.ssl=/(wss)/i.test(this.url),this._reconnectAttempts=0,this.initialTimeout=500,this.maxTimeout=3e5,this.sendQueue=[],this.onOpenCallbacks=[],this.onMessageCallbacks=[],this.onErrorCallbacks=[],this.onCloseCallbacks=[],o(this._readyStateConstants),t?this._connect():this._setInternalState(0)}return u.prototype._readyStateConstants={CONNECTING:0,OPEN:1,CLOSING:2,CLOSED:3,RECONNECT_ABORTED:4},u.prototype._reconnectableStatusCodes=[4e3],u.prototype.close=function(t){return(t||!this.socket.bufferedAmount)&&this.socket.close(),this},u.prototype._connect=function(t){(t||!this.socket||this.socket.readyState!==this._readyStateConstants.OPEN)&&(this.socket=c.createWebSocketBackend(this.url,this.protocols),this.socket.onopen=this._onOpenHandler.bind(this),this.socket.onmessage=this._onMessageHandler.bind(this),this.socket.onerror=this._onErrorHandler.bind(this),this.socket.onclose=this._onCloseHandler.bind(this))},u.prototype.fireQueue=function(){for(;this.sendQueue.length&&this.socket.readyState===this._readyStateConstants.OPEN;){var t=this.sendQueue.shift();this.socket.send(s(t.message)?t.message:JSON.stringify(t.message)),t.deferred.resolve()}},u.prototype.notifyOpenCallbacks=function(){for(var t=0;t<this.onOpenCallbacks.length;t++)this.onOpenCallbacks[t].call(this)},u.prototype.notifyCloseCallbacks=function(t){for(var e=0;e<this.onCloseCallbacks.length;e++)this.onCloseCallbacks[e].call(this,t)},u.prototype.notifyErrorCallbacks=function(t){for(var e=0;e<this.onErrorCallbacks.length;e++)this.onErrorCallbacks[e].call(this,t)},u.prototype.onOpen=function(t){return this.onOpenCallbacks.push(t),this},u.prototype.onClose=function(t){return this.onCloseCallbacks.push(t),this},u.prototype.onError=function(t){return this.onErrorCallbacks.push(t),this},u.prototype.onMessage=function(t,e){if(!i(t))throw new Error("Callback must be a function");if(e&&a(e.filter)&&!s(e.filter)&&!(e.filter instanceof RegExp))throw new Error("Pattern must be a string or regular expression");return this.onMessageCallbacks.push({fn:t,pattern:e?e.filter:void 0,autoApply:e?e.autoApply:!0}),this},u.prototype._onOpenHandler=function(){this._reconnectAttempts=0,this.notifyOpenCallbacks(),this.fireQueue()},u.prototype._onCloseHandler=function(t){this.notifyCloseCallbacks(t),this._reconnectableStatusCodes.indexOf(t.code)>-1&&this.reconnect()},u.prototype._onErrorHandler=function(t){this.notifyErrorCallbacks(t)},u.prototype._onMessageHandler=function(t){for(var e,n,o=this,r=0;r<o.onMessageCallbacks.length;r++)n=o.onMessageCallbacks[r],e=n.pattern,e?s(e)&&t.data===e?(n.fn.call(this,t),h(n.autoApply)):e instanceof RegExp&&e.exec(t.data)&&(n.fn.call(this,t),h(n.autoApply)):(n.fn.call(this,t),h(n.autoApply))},u.prototype.send=function(t){function n(t){t.cancel=o;var e=t.then;return t.then=function(){var t=e.apply(this,arguments);return n(t)},t}function o(e){return s.sendQueue.splice(s.sendQueue.indexOf(t),1),r.reject(e),this}var r=e.defer(),s=this,i=n(r.promise);return s.readyState===s._readyStateConstants.RECONNECT_ABORTED?r.reject("Socket connection has been closed"):(this.sendQueue.push({message:t,deferred:r}),this.fireQueue()),i},u.prototype.reconnect=function(){return this.close(),n(angular.bind(this,function(){this._connect()}),this._getBackoffDelay(++this._reconnectAttempts),!0),this},u.prototype._getBackoffDelay=function(t){var e=Math.random()+1,n=this.initialTimeout,o=2,r=t,s=this.maxTimeout;return Math.floor(Math.min(e*n*Math.pow(o,r),s))},u.prototype._setInternalState=function(t){if(Math.floor(t)!==t||0>t||t>4)throw new Error("state must be an integer between 0 and 4, got: "+t);r||(this.readyState=t||this.socket.readyState),this._internalConnectionState=t,angular.forEach(this.sendQueue,function(t){t.deferred.reject("Message cancelled due to closed socket connection")})},r&&r(u.prototype,"readyState",{get:function(){return this._internalConnectionState||this.socket.readyState},set:function(){throw new Error("The readyState property is read-only")}}),function(t,e){return new u(t,e)}}function e(t){this.createWebSocketBackend=function(e,n){var o,r,s=/wss?:\/\//.exec(e);if(!s)throw new Error("Invalid url provided");if("object"==typeof exports&&require)try{r=require("ws"),o=r.Client||r.client||r}catch(i){}return o=o||t.WebSocket||t.MozWebSocket,n?new o(e,n):new o(e)}}var n=function(){},o=Object.freeze?Object.freeze:n,r=Object.defineProperty,s=angular.isString,i=angular.isFunction,a=angular.isDefined,c=Array.prototype.slice,l=angular.isArray;Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var e=this.length>>>0,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=e);e>n;n++)if(n in this&&this[n]===t)return n;return-1}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=c.call(arguments,1),n=this,o=function(){},r=function(){return n.apply(this instanceof o&&t?this:t,e.concat(c.call(arguments)))};return o.prototype=this.prototype,r.prototype=new o,r}),t.$inject=["$rootScope","$q","$timeout","$websocketBackend"],e.$inject=["$window"],angular.module("ngWebSocket",[]).factory("$websocket",t).factory("WebSocket",t).service("$websocketBackend",e).service("WebSocketBackend",e),angular.module("angular-websocket",["ngWebSocket"])}(); | ||
!function(){"use strict";function t(t,e,o,u){function p(e,o,r){r||!c(o)||l(o)||(r=o,o=void 0),this.protocols=o,this.url=e||"Missing URL",this.ssl=/(wss)/i.test(this.url),this.scope=r&&r.scope||t,this.rootScopeFailover=r&&r.rootScopeFailover&&!0,this._reconnectAttempts=r&&r.reconnectAttempts||0,this.initialTimeout=r&&r.initialTimeout||500,this.maxTimeout=r&&r.maxTimeout||3e5,this.sendQueue=[],this.onOpenCallbacks=[],this.onMessageCallbacks=[],this.onErrorCallbacks=[],this.onCloseCallbacks=[],n(this._readyStateConstants),e?this._connect():this._setInternalState(0)}return p.prototype._readyStateConstants={CONNECTING:0,OPEN:1,CLOSING:2,CLOSED:3,RECONNECT_ABORTED:4},p.prototype._reconnectableStatusCodes=[4e3],p.prototype.safeDigest=function(t){t&&!this.scope.$$phase&&this.scope.$digest()},p.prototype.bindToScope=function(e){return e&&(this.scope=e,this.rootScopeFailover&&this.scope.$on("$destroy",function(){this.scope=t})),this},p.prototype._connect=function(t){(t||!this.socket||this.socket.readyState!==this._readyStateConstants.OPEN)&&(this.socket=u.create(this.url,this.protocols),this.socket.onopen=this._onOpenHandler.bind(this),this.socket.onmessage=this._onMessageHandler.bind(this),this.socket.onerror=this._onErrorHandler.bind(this),this.socket.onclose=this._onCloseHandler.bind(this))},p.prototype.fireQueue=function(){for(;this.sendQueue.length&&this.socket.readyState===this._readyStateConstants.OPEN;){var t=this.sendQueue.shift();this.socket.send(s(t.message)?t.message:JSON.stringify(t.message)),t.deferred.resolve()}},p.prototype.notifyOpenCallbacks=function(){for(var t=0;t<this.onOpenCallbacks.length;t++)this.onOpenCallbacks[t].call(this)},p.prototype.notifyCloseCallbacks=function(t){for(var e=0;e<this.onCloseCallbacks.length;e++)this.onCloseCallbacks[e].call(this,t)},p.prototype.notifyErrorCallbacks=function(t){for(var e=0;e<this.onErrorCallbacks.length;e++)this.onErrorCallbacks[e].call(this,t)},p.prototype.onOpen=function(t){return this.onOpenCallbacks.push(t),this},p.prototype.onClose=function(t){return this.onCloseCallbacks.push(t),this},p.prototype.onError=function(t){return this.onErrorCallbacks.push(t),this},p.prototype.onMessage=function(t,e){if(!i(t))throw new Error("Callback must be a function");if(e&&a(e.filter)&&!s(e.filter)&&!(e.filter instanceof RegExp))throw new Error("Pattern must be a string or regular expression");return this.onMessageCallbacks.push({fn:t,pattern:e?e.filter:void 0,autoApply:e?e.autoApply:!0}),this},p.prototype._onOpenHandler=function(){this._reconnectAttempts=0,this.notifyOpenCallbacks(),this.fireQueue()},p.prototype._onCloseHandler=function(t){this.notifyCloseCallbacks(t),this._reconnectableStatusCodes.indexOf(t.code)>-1&&this.reconnect()},p.prototype._onErrorHandler=function(t){this.notifyErrorCallbacks(t)},p.prototype._onMessageHandler=function(t){for(var e,o,n=this,r=0;r<n.onMessageCallbacks.length;r++)o=n.onMessageCallbacks[r],e=o.pattern,e?s(e)&&t.data===e?(o.fn.call(n,t),n.safeDigest(o.autoApply)):e instanceof RegExp&&e.exec(t.data)&&(o.fn.call(n,t),n.safeDigest(o.autoApply)):(o.fn.call(n,t),n.safeDigest(o.autoApply))},p.prototype.close=function(t){return(t||!this.socket.bufferedAmount)&&this.socket.close(),this},p.prototype.send=function(t){function o(t){t.cancel=n;var e=t.then;return t.then=function(){var t=e.apply(this,arguments);return o(t)},t}function n(e){return s.sendQueue.splice(s.sendQueue.indexOf(t),1),r.reject(e),s}var r=e.defer(),s=this,i=o(r.promise);return s.readyState===s._readyStateConstants.RECONNECT_ABORTED?r.reject("Socket connection has been closed"):(s.sendQueue.push({message:t,deferred:r}),s.fireQueue()),i},p.prototype.reconnect=function(){var t=this;return t.close(),o(t._connect,t._getBackoffDelay(++t._reconnectAttempts)),t},p.prototype._getBackoffDelay=function(t){var e=Math.random()+1,o=this.initialTimeout,n=2,r=t,s=this.maxTimeout;return Math.floor(Math.min(e*o*Math.pow(n,r),s))},p.prototype._setInternalState=function(t){if(Math.floor(t)!==t||0>t||t>4)throw new Error("state must be an integer between 0 and 4, got: "+t);r||(this.readyState=t||this.socket.readyState),this._internalConnectionState=t,angular.forEach(this.sendQueue,function(t){t.deferred.reject("Message cancelled due to closed socket connection")})},r&&r(p.prototype,"readyState",{get:function(){return this._internalConnectionState||this.socket.readyState},set:function(){throw new Error("The readyState property is read-only")}}),function(t,e){return new p(t,e)}}function e(t,e){this.create=function(e,o){var n,r,s=/wss?:\/\//.exec(e);if(!s)throw new Error("Invalid url provided");if("object"==typeof exports&&require)try{r=require("ws"),n=r.Client||r.client||r}catch(i){}return n=n||t.WebSocket||t.MozWebSocket,o?new n(e,o):new n(e)},this.createWebSocketBackend=function(t,o){return e.warn("Deprecated: Please use .create(url, protocols)"),this.create(t,o)}}var o=angular.noop,n=Object.freeze?Object.freeze:o,r=Object.defineProperty,s=angular.isString,i=angular.isFunction,a=angular.isDefined,c=angular.isObject,l=angular.isArray,u=Array.prototype.slice;Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var e=this.length>>>0,o=Number(arguments[1])||0;for(o=0>o?Math.ceil(o):Math.floor(o),0>o&&(o+=e);e>o;o++)if(o in this&&this[o]===t)return o;return-1}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=u.call(arguments,1),o=this,n=function(){},r=function(){return o.apply(this instanceof n&&t?this:t,e.concat(u.call(arguments)))};return n.prototype=this.prototype,r.prototype=new n,r}),angular.module("ngWebSocket",[]).factory("$websocket",["$rootScope","$q","$timeout","$websocketBackend",t]).factory("WebSocket",["$rootScope","$q","$timeout","WebsocketBackend",t]).service("$websocketBackend",["$window","$log",e]).service("WebSocketBackend",["$window","$log",e]),angular.module("angular-websocket",["ngWebSocket"])}(); | ||
//# sourceMappingURL=angular-websocket.min.js.map |
{ | ||
"name": "angular-websocket", | ||
"version": "1.0.6", | ||
"version": "1.0.7", | ||
"main": "angular-websocket.min.js", | ||
@@ -5,0 +5,0 @@ "description": "An AngularJS 1.x WebSocket service for connecting client applications to servers.", |
@@ -151,2 +151,5 @@ # angular-websocket | ||
* Allow more control over $digest cycle per WebSocket instance | ||
* Add .on(event) | ||
* Include more examples of patterns for realtime Angular apps | ||
* Allow for optional configuration object in $websocket constructor | ||
* Add socket.io support | ||
@@ -156,6 +159,2 @@ * Add SockJS support | ||
* Add PubNub support | ||
* Add .bindToScope method | ||
* Add .on(event) | ||
* Include more examples of patterns for realtime Angular apps | ||
* Allow for optional configuration object in $websocket constructor | ||
@@ -162,0 +161,0 @@ ## License |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
69901
846
162