From 354a3187bd7401582e1d229a531397cd520b9fba Mon Sep 17 00:00:00 2001 From: Jim Cowart Date: Wed, 3 Oct 2012 23:27:14 -0400 Subject: [PATCH] Fixed minor bug on node.js when publishing + no subscribers --- README.md | 4 +-- component.json | 2 +- example/amd/js/libs/postal/postal.js | 35 +++++++++++++----------- example/amd/js/libs/postal/postal.min.js | 4 +-- example/node/client/js/lib/postal.js | 35 +++++++++++++----------- example/node/client/js/lib/postal.min.js | 4 +-- example/node/messaging/postal.js | 35 +++++++++++++----------- example/standard/js/postal.js | 35 +++++++++++++----------- example/standard/js/postal.min.js | 4 +-- lib/browser/classic-resolver.js | 2 +- lib/browser/classic-resolver.min.js | 2 +- lib/browser/postal.js | 35 +++++++++++++----------- lib/browser/postal.min.js | 4 +-- lib/node/classic-resolver.js | 2 +- lib/node/postal.js | 35 +++++++++++++----------- package.json | 2 +- spec/Postal.spec.js | 10 +++++++ src/LocalBus.js | 33 ++++++++++++---------- 18 files changed, 157 insertions(+), 126 deletions(-) diff --git a/README.md b/README.md index fb841c7..334ba9f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Postal.js -## Version 0.7.2 (Dual Licensed [MIT](http://www.opensource.org/licenses/mit-license) & [GPL](http://www.opensource.org/licenses/gpl-license)) +## Version 0.7.3 (Dual Licensed [MIT](http://www.opensource.org/licenses/mit-license) & [GPL](http://www.opensource.org/licenses/gpl-license)) ## What is it? Postal.js is an in-memory message bus - very loosely inspired by [AMQP](http://www.amqp.org/) - written in JavaScript. Postal.js runs in the browser, or on the server-side using Node.js. It takes a familiar "eventing-style" paradigm most JavaScript developers are already used to and extends it by providing "broker" and subscriber implementations which are more sophisticated than what you typically find in simple event delegation. @@ -22,7 +22,7 @@ Postal.js is in good company - there are many options for <airquotes>pub/s ## Recent Updates (IMPORTANT) -Version 0.7.2 of postal has implemented a bindings resolver that aligns with how AMQP handles wildcards in topical bindings. ***Please note that this effectively inverts how postal has handled wildcards up to now***. You can still use the old version of the bindings resolve by including the `classic-resolver.js` file in your project. If you want to use the new resolver, just use postal as-is and know that "#" matches 0 or more "words" (words are period-delimited segments of topics) and "*" matches exactly one word. +Version 0.7.3 of postal has implemented a bindings resolver that aligns with how AMQP handles wildcards in topical bindings. ***Please note that this effectively inverts how postal has handled wildcards up to now***. You can still use the old version of the bindings resolve by including the `classic-resolver.js` file in your project. If you want to use the new resolver, just use postal as-is and know that "#" matches 0 or more "words" (words are period-delimited segments of topics) and "*" matches exactly one word. ### Channels? WAT? A channel is a logical partition of topics. Conceptually, it's like a dedicated highway for a specific set of communication. At first glance it might seem like that's overkill for an environment that runs in an event loop, but it actually proves to be quite useful. Every library has architectural opinions that it either imposes or nudges you toward. Channel-oriented messaging nudges you to separate your communication by bounded context, and enables the kind of fine-tuned visibility you need into the interactions between components as your application grows. diff --git a/component.json b/component.json index d60940b..a9e969e 100644 --- a/component.json +++ b/component.json @@ -1,6 +1,6 @@ { "name": "postal.js", - "version": "0.7.2", + "version": "0.7.3", "main": ["lib/standard/postal.min.js", "lib/standard/postal.js"], "dependencies": { "underscore": "~1.3.0" diff --git a/example/amd/js/libs/postal/postal.js b/example/amd/js/libs/postal/postal.js index 1d7a158..e8c5b6c 100644 --- a/example/amd/js/libs/postal/postal.js +++ b/example/amd/js/libs/postal/postal.js @@ -2,7 +2,7 @@ postal Author: Jim Cowart (http://freshbrewedcode.com/jimcowart) License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license) - Version 0.7.2 + Version 0.7.3 */ (function ( root, doc, factory ) { if ( typeof define === "function" && define.amd ) { @@ -279,10 +279,10 @@ }; }, - changePriority: function ( subDef ) { + changePriority : function ( subDef ) { var idx, found; - if(this.subscriptions[subDef.channel] && this.subscriptions[subDef.channel][subDef.topic]) { - this.subscriptions[subDef.channel][subDef.topic] = _.without(this.subscriptions[subDef.channel][subDef.topic], subDef); + if ( this.subscriptions[subDef.channel] && this.subscriptions[subDef.channel][subDef.topic] ) { + this.subscriptions[subDef.channel][subDef.topic] = _.without( this.subscriptions[subDef.channel][subDef.topic], subDef ); idx = this.subscriptions[subDef.channel][subDef.topic].length - 1; for ( ; idx >= 0; idx-- ) { if ( this.subscriptions[subDef.channel][subDef.topic][idx].priority <= subDef.priority ) { @@ -302,21 +302,24 @@ tap( envelope.data, envelope ); } ); - _.each( this.subscriptions[envelope.channel], function ( topic ) { - // TODO: research faster ways to handle this than _.clone - _.each( _.clone(topic), function ( subDef ) { - if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { - if ( _.all( subDef.constraints, function ( constraint ) { - return constraint( envelope.data, envelope ); - } ) ) { - if ( typeof subDef.callback === 'function' ) { - subDef.callback.apply( subDef.context, [envelope.data, envelope] ); - subDef.onHandled(); + if ( this.subscriptions[envelope.channel] ) { + _.each( this.subscriptions[envelope.channel], function ( topic ) { + // TODO: research faster ways to handle this than _.clone + _.each( _.clone( topic ), function ( subDef ) { + if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { + if ( _.all( subDef.constraints, function ( constraint ) { + return constraint( envelope.data, envelope ); + } ) ) { + if ( typeof subDef.callback === 'function' ) { + subDef.callback.apply( subDef.context, [envelope.data, envelope] ); + subDef.onHandled(); + } } } - } + } ); } ); - } ); + } + }, reset : function () { diff --git a/example/amd/js/libs/postal/postal.min.js b/example/amd/js/libs/postal/postal.min.js index da8f585..571da5f 100644 --- a/example/amd/js/libs/postal/postal.min.js +++ b/example/amd/js/libs/postal/postal.min.js @@ -2,6 +2,6 @@ postal Author: Jim Cowart (http://freshbrewedcode.com/jimcowart) License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license) - Version 0.7.2 + Version 0.7.3 */ -(function(e,t,n){typeof define=="function"&&define.amd?define(["underscore"],function(r){return n(r,e,t)}):n(e._,e,t)})(this,document,function(e,t,n,r){var i="/",s=50,o=0,u="postal",a=function(){},f=function(){var t;return function(n){var r=!1;return e.isString(n)?(r=n===t,t=n):(r=e.isEqual(n,t),t=e.clone(n)),!r}},l=function(){var t=[];return function(n){var r=!e.any(t,function(t){return e.isObject(n)||e.isArray(n)?e.isEqual(n,t):n===t});return r&&t.push(n),r}},c=function(e,t){this.channel=e||i,this._topic=t||""};c.prototype={subscribe:function(){var e=arguments.length;if(e===1)return new h(this.channel,this._topic,arguments[0]);if(e===2)return new h(this.channel,arguments[0],arguments[1])},publish:function(e){var t=e||{},n={channel:this.channel,topic:this._topic,data:t};return t.topic&&t.data&&(n=t,n.channel=n.channel||this.channel),n.timeStamp=new Date,y.configuration.bus.publish(n),n},topic:function(e){return e===this._topic?this:new c(this.channel,e)}};var h=function(e,t,n){this.channel=e,this.topic=t,this.callback=n,this.priority=s,this.constraints=new Array(0),this.maxCalls=o,this.onHandled=a,this.context=null,y.configuration.bus.publish({channel:u,topic:"subscription.created",timeStamp:new Date,data:{event:"subscription.created",channel:e,topic:t}}),y.configuration.bus.subscribe(this)};h.prototype={unsubscribe:function(){y.configuration.bus.unsubscribe(this),y.configuration.bus.publish({channel:u,topic:"subscription.removed",timeStamp:new Date,data:{event:"subscription.removed",channel:this.channel,topic:this.topic}})},defer:function(){var e=this.callback;return this.callback=function(t){setTimeout(e,0,t)},this},disposeAfter:function(t){if(e.isNaN(t)||t<=0)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var n=this.onHandled,r=e.after(t,e.bind(function(){this.unsubscribe(this)},this));return this.onHandled=function(){n.apply(this.context,arguments),r()},this},distinctUntilChanged:function(){return this.withConstraint(new f),this},distinct:function(){return this.withConstraint(new l),this},withConstraint:function(t){if(!e.isFunction(t))throw"Predicate constraint must be a function";return this.constraints.push(t),this},withConstraints:function(t){var n=this;return e.isArray(t)&&e.each(t,function(e){n.withConstraint(e)}),n},withContext:function(e){return this.context=e,this},withDebounce:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.debounce(n,t),this},withDelay:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=function(e){setTimeout(function(){n(e)},t)},this},withPriority:function(t){if(e.isNaN(t))throw"Priority must be a number";return this.priority=t,y.configuration.bus.changePriority(this),this},withThrottle:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.throttle(n,t),this},subscribe:function(e){return this.callback=e,this}};var p={cache:{},compare:function(e,t){if(this.cache[t]&&this.cache[t][e])return!0;var n=("^"+e.replace(/\./g,"\\.").replace(/\*/g,"[A-Z,a-z,0-9]*").replace(/#/g,".*")+"$").replace("\\..*$","(\\..*)*$").replace("^.*\\.","^(.*\\.)*"),r=new RegExp(n),i=r.test(t);return i&&(this.cache[t]||(this.cache[t]={}),this.cache[t][e]=!0),i},reset:function(){this.cache={}}},d={addWireTap:function(e){var t=this;return t.wireTaps.push(e),function(){var n=t.wireTaps.indexOf(e);n!==-1&&t.wireTaps.splice(n,1)}},changePriority:function(t){var n,r;if(this.subscriptions[t.channel]&&this.subscriptions[t.channel][t.topic]){this.subscriptions[t.channel][t.topic]=e.without(this.subscriptions[t.channel][t.topic],t),n=this.subscriptions[t.channel][t.topic].length-1;for(;n>=0;n--)if(this.subscriptions[t.channel][t.topic][n].priority<=t.priority){this.subscriptions[t.channel][t.topic].splice(n+1,0,t),r=!0;break}r||this.subscriptions[t.channel][t.topic].unshift(t)}},publish:function(t){e.each(this.wireTaps,function(e){e(t.data,t)}),e.each(this.subscriptions[t.channel],function(n){e.each(e.clone(n),function(n){y.configuration.resolver.compare(n.topic,t.topic)&&e.all(n.constraints,function(e){return e(t.data,t)})&&typeof n.callback=="function"&&(n.callback.apply(n.context,[t.data,t]),n.onHandled())})})},reset:function(){this.subscriptions&&(e.each(this.subscriptions,function(t){e.each(t,function(e){while(e.length)e.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(e){var t,n,r,i=this.subscriptions[e.channel],s;return i||(i=this.subscriptions[e.channel]={}),s=this.subscriptions[e.channel][e.topic],s||(s=this.subscriptions[e.channel][e.topic]=new Array(0)),s.push(e),e},subscriptions:{},wireTaps:new Array(0),unsubscribe:function(e){if(this.subscriptions[e.channel][e.topic]){var t=this.subscriptions[e.channel][e.topic].length,n=0;for(;n=0;n--)if(this.subscriptions[t.channel][t.topic][n].priority<=t.priority){this.subscriptions[t.channel][t.topic].splice(n+1,0,t),r=!0;break}r||this.subscriptions[t.channel][t.topic].unshift(t)}},publish:function(t){e.each(this.wireTaps,function(e){e(t.data,t)}),this.subscriptions[t.channel]&&e.each(this.subscriptions[t.channel],function(n){e.each(e.clone(n),function(n){y.configuration.resolver.compare(n.topic,t.topic)&&e.all(n.constraints,function(e){return e(t.data,t)})&&typeof n.callback=="function"&&(n.callback.apply(n.context,[t.data,t]),n.onHandled())})})},reset:function(){this.subscriptions&&(e.each(this.subscriptions,function(t){e.each(t,function(e){while(e.length)e.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(e){var t,n,r,i=this.subscriptions[e.channel],s;return i||(i=this.subscriptions[e.channel]={}),s=this.subscriptions[e.channel][e.topic],s||(s=this.subscriptions[e.channel][e.topic]=new Array(0)),s.push(e),e},subscriptions:{},wireTaps:new Array(0),unsubscribe:function(e){if(this.subscriptions[e.channel][e.topic]){var t=this.subscriptions[e.channel][e.topic].length,n=0;for(;n= 0; idx-- ) { if ( this.subscriptions[subDef.channel][subDef.topic][idx].priority <= subDef.priority ) { @@ -302,21 +302,24 @@ tap( envelope.data, envelope ); } ); - _.each( this.subscriptions[envelope.channel], function ( topic ) { - // TODO: research faster ways to handle this than _.clone - _.each( _.clone(topic), function ( subDef ) { - if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { - if ( _.all( subDef.constraints, function ( constraint ) { - return constraint( envelope.data, envelope ); - } ) ) { - if ( typeof subDef.callback === 'function' ) { - subDef.callback.apply( subDef.context, [envelope.data, envelope] ); - subDef.onHandled(); + if ( this.subscriptions[envelope.channel] ) { + _.each( this.subscriptions[envelope.channel], function ( topic ) { + // TODO: research faster ways to handle this than _.clone + _.each( _.clone( topic ), function ( subDef ) { + if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { + if ( _.all( subDef.constraints, function ( constraint ) { + return constraint( envelope.data, envelope ); + } ) ) { + if ( typeof subDef.callback === 'function' ) { + subDef.callback.apply( subDef.context, [envelope.data, envelope] ); + subDef.onHandled(); + } } } - } + } ); } ); - } ); + } + }, reset : function () { diff --git a/example/node/client/js/lib/postal.min.js b/example/node/client/js/lib/postal.min.js index da8f585..571da5f 100644 --- a/example/node/client/js/lib/postal.min.js +++ b/example/node/client/js/lib/postal.min.js @@ -2,6 +2,6 @@ postal Author: Jim Cowart (http://freshbrewedcode.com/jimcowart) License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license) - Version 0.7.2 + Version 0.7.3 */ -(function(e,t,n){typeof define=="function"&&define.amd?define(["underscore"],function(r){return n(r,e,t)}):n(e._,e,t)})(this,document,function(e,t,n,r){var i="/",s=50,o=0,u="postal",a=function(){},f=function(){var t;return function(n){var r=!1;return e.isString(n)?(r=n===t,t=n):(r=e.isEqual(n,t),t=e.clone(n)),!r}},l=function(){var t=[];return function(n){var r=!e.any(t,function(t){return e.isObject(n)||e.isArray(n)?e.isEqual(n,t):n===t});return r&&t.push(n),r}},c=function(e,t){this.channel=e||i,this._topic=t||""};c.prototype={subscribe:function(){var e=arguments.length;if(e===1)return new h(this.channel,this._topic,arguments[0]);if(e===2)return new h(this.channel,arguments[0],arguments[1])},publish:function(e){var t=e||{},n={channel:this.channel,topic:this._topic,data:t};return t.topic&&t.data&&(n=t,n.channel=n.channel||this.channel),n.timeStamp=new Date,y.configuration.bus.publish(n),n},topic:function(e){return e===this._topic?this:new c(this.channel,e)}};var h=function(e,t,n){this.channel=e,this.topic=t,this.callback=n,this.priority=s,this.constraints=new Array(0),this.maxCalls=o,this.onHandled=a,this.context=null,y.configuration.bus.publish({channel:u,topic:"subscription.created",timeStamp:new Date,data:{event:"subscription.created",channel:e,topic:t}}),y.configuration.bus.subscribe(this)};h.prototype={unsubscribe:function(){y.configuration.bus.unsubscribe(this),y.configuration.bus.publish({channel:u,topic:"subscription.removed",timeStamp:new Date,data:{event:"subscription.removed",channel:this.channel,topic:this.topic}})},defer:function(){var e=this.callback;return this.callback=function(t){setTimeout(e,0,t)},this},disposeAfter:function(t){if(e.isNaN(t)||t<=0)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var n=this.onHandled,r=e.after(t,e.bind(function(){this.unsubscribe(this)},this));return this.onHandled=function(){n.apply(this.context,arguments),r()},this},distinctUntilChanged:function(){return this.withConstraint(new f),this},distinct:function(){return this.withConstraint(new l),this},withConstraint:function(t){if(!e.isFunction(t))throw"Predicate constraint must be a function";return this.constraints.push(t),this},withConstraints:function(t){var n=this;return e.isArray(t)&&e.each(t,function(e){n.withConstraint(e)}),n},withContext:function(e){return this.context=e,this},withDebounce:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.debounce(n,t),this},withDelay:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=function(e){setTimeout(function(){n(e)},t)},this},withPriority:function(t){if(e.isNaN(t))throw"Priority must be a number";return this.priority=t,y.configuration.bus.changePriority(this),this},withThrottle:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.throttle(n,t),this},subscribe:function(e){return this.callback=e,this}};var p={cache:{},compare:function(e,t){if(this.cache[t]&&this.cache[t][e])return!0;var n=("^"+e.replace(/\./g,"\\.").replace(/\*/g,"[A-Z,a-z,0-9]*").replace(/#/g,".*")+"$").replace("\\..*$","(\\..*)*$").replace("^.*\\.","^(.*\\.)*"),r=new RegExp(n),i=r.test(t);return i&&(this.cache[t]||(this.cache[t]={}),this.cache[t][e]=!0),i},reset:function(){this.cache={}}},d={addWireTap:function(e){var t=this;return t.wireTaps.push(e),function(){var n=t.wireTaps.indexOf(e);n!==-1&&t.wireTaps.splice(n,1)}},changePriority:function(t){var n,r;if(this.subscriptions[t.channel]&&this.subscriptions[t.channel][t.topic]){this.subscriptions[t.channel][t.topic]=e.without(this.subscriptions[t.channel][t.topic],t),n=this.subscriptions[t.channel][t.topic].length-1;for(;n>=0;n--)if(this.subscriptions[t.channel][t.topic][n].priority<=t.priority){this.subscriptions[t.channel][t.topic].splice(n+1,0,t),r=!0;break}r||this.subscriptions[t.channel][t.topic].unshift(t)}},publish:function(t){e.each(this.wireTaps,function(e){e(t.data,t)}),e.each(this.subscriptions[t.channel],function(n){e.each(e.clone(n),function(n){y.configuration.resolver.compare(n.topic,t.topic)&&e.all(n.constraints,function(e){return e(t.data,t)})&&typeof n.callback=="function"&&(n.callback.apply(n.context,[t.data,t]),n.onHandled())})})},reset:function(){this.subscriptions&&(e.each(this.subscriptions,function(t){e.each(t,function(e){while(e.length)e.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(e){var t,n,r,i=this.subscriptions[e.channel],s;return i||(i=this.subscriptions[e.channel]={}),s=this.subscriptions[e.channel][e.topic],s||(s=this.subscriptions[e.channel][e.topic]=new Array(0)),s.push(e),e},subscriptions:{},wireTaps:new Array(0),unsubscribe:function(e){if(this.subscriptions[e.channel][e.topic]){var t=this.subscriptions[e.channel][e.topic].length,n=0;for(;n=0;n--)if(this.subscriptions[t.channel][t.topic][n].priority<=t.priority){this.subscriptions[t.channel][t.topic].splice(n+1,0,t),r=!0;break}r||this.subscriptions[t.channel][t.topic].unshift(t)}},publish:function(t){e.each(this.wireTaps,function(e){e(t.data,t)}),this.subscriptions[t.channel]&&e.each(this.subscriptions[t.channel],function(n){e.each(e.clone(n),function(n){y.configuration.resolver.compare(n.topic,t.topic)&&e.all(n.constraints,function(e){return e(t.data,t)})&&typeof n.callback=="function"&&(n.callback.apply(n.context,[t.data,t]),n.onHandled())})})},reset:function(){this.subscriptions&&(e.each(this.subscriptions,function(t){e.each(t,function(e){while(e.length)e.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(e){var t,n,r,i=this.subscriptions[e.channel],s;return i||(i=this.subscriptions[e.channel]={}),s=this.subscriptions[e.channel][e.topic],s||(s=this.subscriptions[e.channel][e.topic]=new Array(0)),s.push(e),e},subscriptions:{},wireTaps:new Array(0),unsubscribe:function(e){if(this.subscriptions[e.channel][e.topic]){var t=this.subscriptions[e.channel][e.topic].length,n=0;for(;n= 0; idx-- ) { if ( this.subscriptions[subDef.channel][subDef.topic][idx].priority <= subDef.priority ) { @@ -294,21 +294,24 @@ var localBus = { tap( envelope.data, envelope ); } ); - _.each( this.subscriptions[envelope.channel], function ( topic ) { - // TODO: research faster ways to handle this than _.clone - _.each( _.clone(topic), function ( subDef ) { - if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { - if ( _.all( subDef.constraints, function ( constraint ) { - return constraint( envelope.data, envelope ); - } ) ) { - if ( typeof subDef.callback === 'function' ) { - subDef.callback.apply( subDef.context, [envelope.data, envelope] ); - subDef.onHandled(); + if ( this.subscriptions[envelope.channel] ) { + _.each( this.subscriptions[envelope.channel], function ( topic ) { + // TODO: research faster ways to handle this than _.clone + _.each( _.clone( topic ), function ( subDef ) { + if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { + if ( _.all( subDef.constraints, function ( constraint ) { + return constraint( envelope.data, envelope ); + } ) ) { + if ( typeof subDef.callback === 'function' ) { + subDef.callback.apply( subDef.context, [envelope.data, envelope] ); + subDef.onHandled(); + } } } - } + } ); } ); - } ); + } + }, reset : function () { diff --git a/example/standard/js/postal.js b/example/standard/js/postal.js index 1d7a158..e8c5b6c 100644 --- a/example/standard/js/postal.js +++ b/example/standard/js/postal.js @@ -2,7 +2,7 @@ postal Author: Jim Cowart (http://freshbrewedcode.com/jimcowart) License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license) - Version 0.7.2 + Version 0.7.3 */ (function ( root, doc, factory ) { if ( typeof define === "function" && define.amd ) { @@ -279,10 +279,10 @@ }; }, - changePriority: function ( subDef ) { + changePriority : function ( subDef ) { var idx, found; - if(this.subscriptions[subDef.channel] && this.subscriptions[subDef.channel][subDef.topic]) { - this.subscriptions[subDef.channel][subDef.topic] = _.without(this.subscriptions[subDef.channel][subDef.topic], subDef); + if ( this.subscriptions[subDef.channel] && this.subscriptions[subDef.channel][subDef.topic] ) { + this.subscriptions[subDef.channel][subDef.topic] = _.without( this.subscriptions[subDef.channel][subDef.topic], subDef ); idx = this.subscriptions[subDef.channel][subDef.topic].length - 1; for ( ; idx >= 0; idx-- ) { if ( this.subscriptions[subDef.channel][subDef.topic][idx].priority <= subDef.priority ) { @@ -302,21 +302,24 @@ tap( envelope.data, envelope ); } ); - _.each( this.subscriptions[envelope.channel], function ( topic ) { - // TODO: research faster ways to handle this than _.clone - _.each( _.clone(topic), function ( subDef ) { - if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { - if ( _.all( subDef.constraints, function ( constraint ) { - return constraint( envelope.data, envelope ); - } ) ) { - if ( typeof subDef.callback === 'function' ) { - subDef.callback.apply( subDef.context, [envelope.data, envelope] ); - subDef.onHandled(); + if ( this.subscriptions[envelope.channel] ) { + _.each( this.subscriptions[envelope.channel], function ( topic ) { + // TODO: research faster ways to handle this than _.clone + _.each( _.clone( topic ), function ( subDef ) { + if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { + if ( _.all( subDef.constraints, function ( constraint ) { + return constraint( envelope.data, envelope ); + } ) ) { + if ( typeof subDef.callback === 'function' ) { + subDef.callback.apply( subDef.context, [envelope.data, envelope] ); + subDef.onHandled(); + } } } - } + } ); } ); - } ); + } + }, reset : function () { diff --git a/example/standard/js/postal.min.js b/example/standard/js/postal.min.js index da8f585..571da5f 100644 --- a/example/standard/js/postal.min.js +++ b/example/standard/js/postal.min.js @@ -2,6 +2,6 @@ postal Author: Jim Cowart (http://freshbrewedcode.com/jimcowart) License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license) - Version 0.7.2 + Version 0.7.3 */ -(function(e,t,n){typeof define=="function"&&define.amd?define(["underscore"],function(r){return n(r,e,t)}):n(e._,e,t)})(this,document,function(e,t,n,r){var i="/",s=50,o=0,u="postal",a=function(){},f=function(){var t;return function(n){var r=!1;return e.isString(n)?(r=n===t,t=n):(r=e.isEqual(n,t),t=e.clone(n)),!r}},l=function(){var t=[];return function(n){var r=!e.any(t,function(t){return e.isObject(n)||e.isArray(n)?e.isEqual(n,t):n===t});return r&&t.push(n),r}},c=function(e,t){this.channel=e||i,this._topic=t||""};c.prototype={subscribe:function(){var e=arguments.length;if(e===1)return new h(this.channel,this._topic,arguments[0]);if(e===2)return new h(this.channel,arguments[0],arguments[1])},publish:function(e){var t=e||{},n={channel:this.channel,topic:this._topic,data:t};return t.topic&&t.data&&(n=t,n.channel=n.channel||this.channel),n.timeStamp=new Date,y.configuration.bus.publish(n),n},topic:function(e){return e===this._topic?this:new c(this.channel,e)}};var h=function(e,t,n){this.channel=e,this.topic=t,this.callback=n,this.priority=s,this.constraints=new Array(0),this.maxCalls=o,this.onHandled=a,this.context=null,y.configuration.bus.publish({channel:u,topic:"subscription.created",timeStamp:new Date,data:{event:"subscription.created",channel:e,topic:t}}),y.configuration.bus.subscribe(this)};h.prototype={unsubscribe:function(){y.configuration.bus.unsubscribe(this),y.configuration.bus.publish({channel:u,topic:"subscription.removed",timeStamp:new Date,data:{event:"subscription.removed",channel:this.channel,topic:this.topic}})},defer:function(){var e=this.callback;return this.callback=function(t){setTimeout(e,0,t)},this},disposeAfter:function(t){if(e.isNaN(t)||t<=0)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var n=this.onHandled,r=e.after(t,e.bind(function(){this.unsubscribe(this)},this));return this.onHandled=function(){n.apply(this.context,arguments),r()},this},distinctUntilChanged:function(){return this.withConstraint(new f),this},distinct:function(){return this.withConstraint(new l),this},withConstraint:function(t){if(!e.isFunction(t))throw"Predicate constraint must be a function";return this.constraints.push(t),this},withConstraints:function(t){var n=this;return e.isArray(t)&&e.each(t,function(e){n.withConstraint(e)}),n},withContext:function(e){return this.context=e,this},withDebounce:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.debounce(n,t),this},withDelay:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=function(e){setTimeout(function(){n(e)},t)},this},withPriority:function(t){if(e.isNaN(t))throw"Priority must be a number";return this.priority=t,y.configuration.bus.changePriority(this),this},withThrottle:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.throttle(n,t),this},subscribe:function(e){return this.callback=e,this}};var p={cache:{},compare:function(e,t){if(this.cache[t]&&this.cache[t][e])return!0;var n=("^"+e.replace(/\./g,"\\.").replace(/\*/g,"[A-Z,a-z,0-9]*").replace(/#/g,".*")+"$").replace("\\..*$","(\\..*)*$").replace("^.*\\.","^(.*\\.)*"),r=new RegExp(n),i=r.test(t);return i&&(this.cache[t]||(this.cache[t]={}),this.cache[t][e]=!0),i},reset:function(){this.cache={}}},d={addWireTap:function(e){var t=this;return t.wireTaps.push(e),function(){var n=t.wireTaps.indexOf(e);n!==-1&&t.wireTaps.splice(n,1)}},changePriority:function(t){var n,r;if(this.subscriptions[t.channel]&&this.subscriptions[t.channel][t.topic]){this.subscriptions[t.channel][t.topic]=e.without(this.subscriptions[t.channel][t.topic],t),n=this.subscriptions[t.channel][t.topic].length-1;for(;n>=0;n--)if(this.subscriptions[t.channel][t.topic][n].priority<=t.priority){this.subscriptions[t.channel][t.topic].splice(n+1,0,t),r=!0;break}r||this.subscriptions[t.channel][t.topic].unshift(t)}},publish:function(t){e.each(this.wireTaps,function(e){e(t.data,t)}),e.each(this.subscriptions[t.channel],function(n){e.each(e.clone(n),function(n){y.configuration.resolver.compare(n.topic,t.topic)&&e.all(n.constraints,function(e){return e(t.data,t)})&&typeof n.callback=="function"&&(n.callback.apply(n.context,[t.data,t]),n.onHandled())})})},reset:function(){this.subscriptions&&(e.each(this.subscriptions,function(t){e.each(t,function(e){while(e.length)e.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(e){var t,n,r,i=this.subscriptions[e.channel],s;return i||(i=this.subscriptions[e.channel]={}),s=this.subscriptions[e.channel][e.topic],s||(s=this.subscriptions[e.channel][e.topic]=new Array(0)),s.push(e),e},subscriptions:{},wireTaps:new Array(0),unsubscribe:function(e){if(this.subscriptions[e.channel][e.topic]){var t=this.subscriptions[e.channel][e.topic].length,n=0;for(;n=0;n--)if(this.subscriptions[t.channel][t.topic][n].priority<=t.priority){this.subscriptions[t.channel][t.topic].splice(n+1,0,t),r=!0;break}r||this.subscriptions[t.channel][t.topic].unshift(t)}},publish:function(t){e.each(this.wireTaps,function(e){e(t.data,t)}),this.subscriptions[t.channel]&&e.each(this.subscriptions[t.channel],function(n){e.each(e.clone(n),function(n){y.configuration.resolver.compare(n.topic,t.topic)&&e.all(n.constraints,function(e){return e(t.data,t)})&&typeof n.callback=="function"&&(n.callback.apply(n.context,[t.data,t]),n.onHandled())})})},reset:function(){this.subscriptions&&(e.each(this.subscriptions,function(t){e.each(t,function(e){while(e.length)e.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(e){var t,n,r,i=this.subscriptions[e.channel],s;return i||(i=this.subscriptions[e.channel]={}),s=this.subscriptions[e.channel][e.topic],s||(s=this.subscriptions[e.channel][e.topic]=new Array(0)),s.push(e),e},subscriptions:{},wireTaps:new Array(0),unsubscribe:function(e){if(this.subscriptions[e.channel][e.topic]){var t=this.subscriptions[e.channel][e.topic].length,n=0;for(;n= 0; idx-- ) { if ( this.subscriptions[subDef.channel][subDef.topic][idx].priority <= subDef.priority ) { @@ -302,21 +302,24 @@ tap( envelope.data, envelope ); } ); - _.each( this.subscriptions[envelope.channel], function ( topic ) { - // TODO: research faster ways to handle this than _.clone - _.each( _.clone(topic), function ( subDef ) { - if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { - if ( _.all( subDef.constraints, function ( constraint ) { - return constraint( envelope.data, envelope ); - } ) ) { - if ( typeof subDef.callback === 'function' ) { - subDef.callback.apply( subDef.context, [envelope.data, envelope] ); - subDef.onHandled(); + if ( this.subscriptions[envelope.channel] ) { + _.each( this.subscriptions[envelope.channel], function ( topic ) { + // TODO: research faster ways to handle this than _.clone + _.each( _.clone( topic ), function ( subDef ) { + if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { + if ( _.all( subDef.constraints, function ( constraint ) { + return constraint( envelope.data, envelope ); + } ) ) { + if ( typeof subDef.callback === 'function' ) { + subDef.callback.apply( subDef.context, [envelope.data, envelope] ); + subDef.onHandled(); + } } } - } + } ); } ); - } ); + } + }, reset : function () { diff --git a/lib/browser/postal.min.js b/lib/browser/postal.min.js index da8f585..571da5f 100644 --- a/lib/browser/postal.min.js +++ b/lib/browser/postal.min.js @@ -2,6 +2,6 @@ postal Author: Jim Cowart (http://freshbrewedcode.com/jimcowart) License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license) - Version 0.7.2 + Version 0.7.3 */ -(function(e,t,n){typeof define=="function"&&define.amd?define(["underscore"],function(r){return n(r,e,t)}):n(e._,e,t)})(this,document,function(e,t,n,r){var i="/",s=50,o=0,u="postal",a=function(){},f=function(){var t;return function(n){var r=!1;return e.isString(n)?(r=n===t,t=n):(r=e.isEqual(n,t),t=e.clone(n)),!r}},l=function(){var t=[];return function(n){var r=!e.any(t,function(t){return e.isObject(n)||e.isArray(n)?e.isEqual(n,t):n===t});return r&&t.push(n),r}},c=function(e,t){this.channel=e||i,this._topic=t||""};c.prototype={subscribe:function(){var e=arguments.length;if(e===1)return new h(this.channel,this._topic,arguments[0]);if(e===2)return new h(this.channel,arguments[0],arguments[1])},publish:function(e){var t=e||{},n={channel:this.channel,topic:this._topic,data:t};return t.topic&&t.data&&(n=t,n.channel=n.channel||this.channel),n.timeStamp=new Date,y.configuration.bus.publish(n),n},topic:function(e){return e===this._topic?this:new c(this.channel,e)}};var h=function(e,t,n){this.channel=e,this.topic=t,this.callback=n,this.priority=s,this.constraints=new Array(0),this.maxCalls=o,this.onHandled=a,this.context=null,y.configuration.bus.publish({channel:u,topic:"subscription.created",timeStamp:new Date,data:{event:"subscription.created",channel:e,topic:t}}),y.configuration.bus.subscribe(this)};h.prototype={unsubscribe:function(){y.configuration.bus.unsubscribe(this),y.configuration.bus.publish({channel:u,topic:"subscription.removed",timeStamp:new Date,data:{event:"subscription.removed",channel:this.channel,topic:this.topic}})},defer:function(){var e=this.callback;return this.callback=function(t){setTimeout(e,0,t)},this},disposeAfter:function(t){if(e.isNaN(t)||t<=0)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var n=this.onHandled,r=e.after(t,e.bind(function(){this.unsubscribe(this)},this));return this.onHandled=function(){n.apply(this.context,arguments),r()},this},distinctUntilChanged:function(){return this.withConstraint(new f),this},distinct:function(){return this.withConstraint(new l),this},withConstraint:function(t){if(!e.isFunction(t))throw"Predicate constraint must be a function";return this.constraints.push(t),this},withConstraints:function(t){var n=this;return e.isArray(t)&&e.each(t,function(e){n.withConstraint(e)}),n},withContext:function(e){return this.context=e,this},withDebounce:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.debounce(n,t),this},withDelay:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=function(e){setTimeout(function(){n(e)},t)},this},withPriority:function(t){if(e.isNaN(t))throw"Priority must be a number";return this.priority=t,y.configuration.bus.changePriority(this),this},withThrottle:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.throttle(n,t),this},subscribe:function(e){return this.callback=e,this}};var p={cache:{},compare:function(e,t){if(this.cache[t]&&this.cache[t][e])return!0;var n=("^"+e.replace(/\./g,"\\.").replace(/\*/g,"[A-Z,a-z,0-9]*").replace(/#/g,".*")+"$").replace("\\..*$","(\\..*)*$").replace("^.*\\.","^(.*\\.)*"),r=new RegExp(n),i=r.test(t);return i&&(this.cache[t]||(this.cache[t]={}),this.cache[t][e]=!0),i},reset:function(){this.cache={}}},d={addWireTap:function(e){var t=this;return t.wireTaps.push(e),function(){var n=t.wireTaps.indexOf(e);n!==-1&&t.wireTaps.splice(n,1)}},changePriority:function(t){var n,r;if(this.subscriptions[t.channel]&&this.subscriptions[t.channel][t.topic]){this.subscriptions[t.channel][t.topic]=e.without(this.subscriptions[t.channel][t.topic],t),n=this.subscriptions[t.channel][t.topic].length-1;for(;n>=0;n--)if(this.subscriptions[t.channel][t.topic][n].priority<=t.priority){this.subscriptions[t.channel][t.topic].splice(n+1,0,t),r=!0;break}r||this.subscriptions[t.channel][t.topic].unshift(t)}},publish:function(t){e.each(this.wireTaps,function(e){e(t.data,t)}),e.each(this.subscriptions[t.channel],function(n){e.each(e.clone(n),function(n){y.configuration.resolver.compare(n.topic,t.topic)&&e.all(n.constraints,function(e){return e(t.data,t)})&&typeof n.callback=="function"&&(n.callback.apply(n.context,[t.data,t]),n.onHandled())})})},reset:function(){this.subscriptions&&(e.each(this.subscriptions,function(t){e.each(t,function(e){while(e.length)e.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(e){var t,n,r,i=this.subscriptions[e.channel],s;return i||(i=this.subscriptions[e.channel]={}),s=this.subscriptions[e.channel][e.topic],s||(s=this.subscriptions[e.channel][e.topic]=new Array(0)),s.push(e),e},subscriptions:{},wireTaps:new Array(0),unsubscribe:function(e){if(this.subscriptions[e.channel][e.topic]){var t=this.subscriptions[e.channel][e.topic].length,n=0;for(;n=0;n--)if(this.subscriptions[t.channel][t.topic][n].priority<=t.priority){this.subscriptions[t.channel][t.topic].splice(n+1,0,t),r=!0;break}r||this.subscriptions[t.channel][t.topic].unshift(t)}},publish:function(t){e.each(this.wireTaps,function(e){e(t.data,t)}),this.subscriptions[t.channel]&&e.each(this.subscriptions[t.channel],function(n){e.each(e.clone(n),function(n){y.configuration.resolver.compare(n.topic,t.topic)&&e.all(n.constraints,function(e){return e(t.data,t)})&&typeof n.callback=="function"&&(n.callback.apply(n.context,[t.data,t]),n.onHandled())})})},reset:function(){this.subscriptions&&(e.each(this.subscriptions,function(t){e.each(t,function(e){while(e.length)e.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(e){var t,n,r,i=this.subscriptions[e.channel],s;return i||(i=this.subscriptions[e.channel]={}),s=this.subscriptions[e.channel][e.topic],s||(s=this.subscriptions[e.channel][e.topic]=new Array(0)),s.push(e),e},subscriptions:{},wireTaps:new Array(0),unsubscribe:function(e){if(this.subscriptions[e.channel][e.topic]){var t=this.subscriptions[e.channel][e.topic].length,n=0;for(;n= 0; idx-- ) { if ( this.subscriptions[subDef.channel][subDef.topic][idx].priority <= subDef.priority ) { @@ -294,21 +294,24 @@ var localBus = { tap( envelope.data, envelope ); } ); - _.each( this.subscriptions[envelope.channel], function ( topic ) { - // TODO: research faster ways to handle this than _.clone - _.each( _.clone(topic), function ( subDef ) { - if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { - if ( _.all( subDef.constraints, function ( constraint ) { - return constraint( envelope.data, envelope ); - } ) ) { - if ( typeof subDef.callback === 'function' ) { - subDef.callback.apply( subDef.context, [envelope.data, envelope] ); - subDef.onHandled(); + if ( this.subscriptions[envelope.channel] ) { + _.each( this.subscriptions[envelope.channel], function ( topic ) { + // TODO: research faster ways to handle this than _.clone + _.each( _.clone( topic ), function ( subDef ) { + if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { + if ( _.all( subDef.constraints, function ( constraint ) { + return constraint( envelope.data, envelope ); + } ) ) { + if ( typeof subDef.callback === 'function' ) { + subDef.callback.apply( subDef.context, [envelope.data, envelope] ); + subDef.onHandled(); + } } } - } + } ); } ); - } ); + } + }, reset : function () { diff --git a/package.json b/package.json index 18c0e0a..a5795a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name" : "postal", "description" : "Pub/Sub library providing wildcard subscriptions, complex message handling, etc. Works server and client-side.", - "version" : "0.7.2", + "version" : "0.7.3", "homepage" : "http://github.com/ifandelse/postal.js", "repository" : { "type" : "git", diff --git a/spec/Postal.spec.js b/spec/Postal.spec.js index 976f149..fd18057 100644 --- a/spec/Postal.spec.js +++ b/spec/Postal.spec.js @@ -864,5 +864,15 @@ QUnit.specify( "postal.js", function () { assert( results.length ).equals( 10 ); } ); } ); + describe( "When publishing on a channel where no subscribers exist", function () { + it( "should return expected results for MyChannel/MyTopic", function () { + var env = postal.publish({ + channel: "NoOneIsUsingThisOne", + topic: "This.Is.A.Lonely.Topic", + data: "Y U NO SUBSCRIBE TO ME?" + }); + assert( !_.isEmpty(env) ).equals( true ); + } ); + } ); } ); } ); \ No newline at end of file diff --git a/src/LocalBus.js b/src/LocalBus.js index fd7c47d..7c39579 100644 --- a/src/LocalBus.js +++ b/src/LocalBus.js @@ -11,10 +11,10 @@ var localBus = { }; }, - changePriority: function ( subDef ) { + changePriority : function ( subDef ) { var idx, found; - if(this.subscriptions[subDef.channel] && this.subscriptions[subDef.channel][subDef.topic]) { - this.subscriptions[subDef.channel][subDef.topic] = _.without(this.subscriptions[subDef.channel][subDef.topic], subDef); + if ( this.subscriptions[subDef.channel] && this.subscriptions[subDef.channel][subDef.topic] ) { + this.subscriptions[subDef.channel][subDef.topic] = _.without( this.subscriptions[subDef.channel][subDef.topic], subDef ); idx = this.subscriptions[subDef.channel][subDef.topic].length - 1; for ( ; idx >= 0; idx-- ) { if ( this.subscriptions[subDef.channel][subDef.topic][idx].priority <= subDef.priority ) { @@ -34,21 +34,24 @@ var localBus = { tap( envelope.data, envelope ); } ); - _.each( this.subscriptions[envelope.channel], function ( topic ) { - // TODO: research faster ways to handle this than _.clone - _.each( _.clone(topic), function ( subDef ) { - if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { - if ( _.all( subDef.constraints, function ( constraint ) { - return constraint( envelope.data, envelope ); - } ) ) { - if ( typeof subDef.callback === 'function' ) { - subDef.callback.apply( subDef.context, [envelope.data, envelope] ); - subDef.onHandled(); + if ( this.subscriptions[envelope.channel] ) { + _.each( this.subscriptions[envelope.channel], function ( topic ) { + // TODO: research faster ways to handle this than _.clone + _.each( _.clone( topic ), function ( subDef ) { + if ( postal.configuration.resolver.compare( subDef.topic, envelope.topic ) ) { + if ( _.all( subDef.constraints, function ( constraint ) { + return constraint( envelope.data, envelope ); + } ) ) { + if ( typeof subDef.callback === 'function' ) { + subDef.callback.apply( subDef.context, [envelope.data, envelope] ); + subDef.onHandled(); + } } } - } + } ); } ); - } ); + } + }, reset : function () {