PubSubway
Plain pubsub module with a spice of logic to when subscribers get the message.
Have you ever had
- Code you wanted to only invoke once - but with a message that repeats?
- Code you wanted to only invoke when a range of messages have all been published (in random order)?
- Code you wanted to pause invoking at speciffic conditions?
Of cause you have... cause thats what real world code needs.
And everytime you have dealt with it by making some good counters around your pubsub structure and build nicely structured features to take care of when to invoke and when not to.
PubSubway replaces the counters and the logic around your observer pattern with easy to read chuncks of code with a light footprint.
Just take the subway instead of sitting in the trafic jam...
Example:
var db = require('mysql');
var go = require('pubsubway');
var mysql = createConnection(db);
mysql.query('UPDATE product SET stock = 7 WHERE id = 423', function() {
go.yell('/sql_a/done')
});
mysql.query('UPDATE product SET stock = 2 WHERE id = 332', function() {
go.yell('/sql_b/done')
});
go.whenAND(['/sql_a/done', '/sql_b/done'], function() {
console.log('Both SQL a and SQL b are done now');
});
To use in regular browser instead of Node please include via unpkg
<script src="https://unpkg.com/pubsubway"></script>
The global scope will be poluted populated with the object pubsubway
- please note that all examples on this site uses go
to illustrate the PubSubWay object.
Involvement
Any involvement in the project is very welcome, and encouraged.
The pubsub pattern
Please remember that the pubsub style of programing (observer pattern) is best suited to publish messages about what has happened. Dont fall into the pifall of using it as regular functions. A good idea is to label your topics in past sense.
Documentation
You include the module with a traditional var go = require('pubsubway');
(or any name you find suitable). In the documentation I chose go
cause it short and sounds nice.
Publish a message
go.pub =
go.yell =
go.publish = function(
topic, /* string */
args /* array */
)
Subscribe to a message
To listen to a single message and invoke code is trivial - but when you want to listen to several messages you are suddenly left with a lot of choises recarding how to handle the logic around it.
Subscribe to any of these messages (OR mode)
go.sub =
go.when =
go.subOR =
go.whenOR =
go.subscribe = function( topic /* string || array */
,
callback /* Function */
,
subscribeFirst /* [bool] */
,
mode /* string */
)
Example
go.subscribe("/foo/bar", function(a, b, c){
...
});
Subscribe to any of these messages (OR mode) and invoke only once
go.sub1 =
go.when1 =
go.subOR1 =
go.whenOR1 =
go.subscribeOnce = function( topic /* string || array */
,
callback /* Function */
,
subscribeFirst /* [bool] */
,
mode /* string */
)
Subscribe to all these messages = only start invoking when all of them have been published (AND mode)
go.subAND =
go.whenAND =
go.subscribeAND =
go.subscribeANDmodeContinues = function(
topic /* string || array */
,
callback /* Function */
,
subscribeFirst /* [bool] */
)
me.subAND1 =
me.whenAND1 =
me.subscribeANDmodeOnce = function(
topic /* string || array */
,
callback /* Function */
,
subscribeFirst /* [bool] */
){
//ToDo:implement reset
me.subscribe(topic, callback, subscribeFirst, 'ANDmodeOnce')
};
Subscribe to messages but only start invoking each time all of them have been published again.
go.subREWIND =
go.whenREWIND =
go.subscribeREWIND =
go.subscribeANDmodeRewind = function(
topic /* string || array */
,
callback /* Function */
,
subscribeFirst /* [bool] */
)
Subscribe to messages but pause and restart with
go.whenORBUT =
go.subORBUT =
go.subscribeORmodeButNotIfButResetWith = function(
topic /* string || array */
,
butNotIf /* string || array */
,
resetWith /* string || array */
,
callback /* Function */
,
subscribeFirst /* [bool] */
)
Unsubscribe a subscription
go.unsub =
go.unsubscribe = function(handle /* Array */){
// var handle = pubsubway.subscribe("/foo", function(){});
// pubsubway.unsubscribe(handle);
// ToDo: make it possible to resubscribe a handle
// ToDo: implement go.subways[uid].handlers check
Log the publications
go.log = function(/* string */ msg, /* integer */ level){
// log events -
// Please overwrite behavior with something like
// $.log = function(msg){alert(msg)}
if(doLog && level<=100){
console.log('pub/sub: ' + msg);
}
};
Start/stop logging
go.doLog = function(/*bool*/ val)
Stop all publications
The big handbrake
go.voidAction = function(/*bool*/ val){
Wrap topics
Wrab topics to act like traditional callback function to handle strings as callbacks
// Make it convinient to publish string instead of sending function as callback
// Use in your own funktion like:
// callback_function = go.pubsubBack(topic /* sting */)
// to be able to put a function or a string to publish as your own callback
go.pubsubBack(topic /* sting */)
ToDo
-
Tests: The module is used and enchanged in production - so it works, but better get those tests up and running...
-
pubAlert: optional Log warning when something is published that nothing is subscribed to. Good fro development.
-
pubBuffer: Setting to buffer all publications untill released. Good for when you publish things in your sync flow, but want to message something that will be observing a little later caused by async waiting. Is it bad structure of the code? well, if it is used in the main flow it is, but during the initial load of code it is not.
-
Mode strings to mode vars To make the minifyed version smaller all the hardcoded strings for mode should be a variable returned by a function.
tl;dr
License: MIT
Pattern: Observer
Inspiration: Loosely based on jQuery pub/sub plugin by Peter Higgins, expanded in scope. Rewritten blindly.