forked from daniellmb/MinPubSub
-
Notifications
You must be signed in to change notification settings - Fork 15
/
pubsub.js
170 lines (153 loc) · 3.93 KB
/
pubsub.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/**
* pubsub.js
*
* A tiny, optimized, tested, standalone and robust
* pubsub implementation supporting different javascript environments
*
* @author Federico "Lox" Lucignano <http://plus.ly/federico.lox>
*
* @see https://github.com/federico-lox/pubsub.js
*/
/*global define, module*/
(function (context) {
'use strict';
/**
* @private
*/
function init() {
//the channel subscription hash
var channels = {},
//help minification
funcType = Function;
return {
/*
* @public
*
* Publish some data on a channel
*
* @param String channel The channel to publish on
* @param Mixed argument The data to publish, the function supports
* as many data parameters as needed
*
* @example Publish stuff on '/some/channel'.
* Anything subscribed will be called with a function
* signature like: function(a,b,c){ ... }
*
* PubSub.publish(
* "/some/channel", "a", "b",
* {total: 10, min: 1, max: 3}
* );
*/
publish: function () {
//help minification
var args = arguments,
// args[0] is the channel
subs = channels[args[0]],
len,
params,
x;
if (subs) {
len = subs.length;
params = (args.length > 1) ?
Array.prototype.splice.call(args, 1) : [];
//run the callbacks asynchronously,
//do not block the main execution process
setTimeout(
function () {
//executes callbacks in the order
//in which they were registered
for (x = 0; x < len; x += 1) {
subs[x].apply(context, params);
}
//clear references to allow garbage collection
subs = context = params = null;
},
0
);
}
},
/*
* @public
*
* Register a callback on a channel
*
* @param String channel The channel to subscribe to
* @param Function callback The event handler, any time something is
* published on a subscribed channel, the callback will be called
* with the published array as ordered arguments
*
* @return Array A handle which can be used to unsubscribe this
* particular subscription
*
* @example PubSub.subscribe(
* "/some/channel",
* function(a, b, c){ ... }
* );
*/
subscribe: function (channel, callback) {
if (typeof channel !== 'string') {
throw "invalid or missing channel";
}
if (!(callback instanceof funcType)) {
throw "invalid or missing callback";
}
if (!channels[channel]) {
channels[channel] = [];
}
channels[channel].push(callback);
return {channel: channel, callback: callback};
},
/*
* @public
*
* Disconnect a subscribed function f.
*
* @param Mixed handle The return value from a subscribe call or the
* name of a channel as a String
* @param Function callback [OPTIONAL] The event handler originaally
* registered, not needed if handle contains the return value
* of subscribe
*
* @example
* var handle = PubSub.subscribe("/some/channel", function(){});
* PubSub.unsubscribe(handle);
*
* or
*
* PubSub.unsubscribe("/some/channel", callback);
*/
unsubscribe: function (handle, callback) {
if (handle.channel && handle.callback) {
callback = handle.callback;
handle = handle.channel;
}
if (typeof handle !== 'string') {
throw "invalid or missing channel";
}
if (!(callback instanceof funcType)) {
throw "invalid or missing callback";
}
var subs = channels[handle],
x,
y = (subs instanceof Array) ? subs.length : 0;
for (x = 0; x < y; x += 1) {
if (subs[x] === callback) {
subs.splice(x, 1);
break;
}
}
}
};
}
//UMD
if (typeof define === 'function' && define.amd) {
//AMD module
define('pubsub', init);
} else if (typeof module === 'object' && module.exports) {
//CommonJS module
module.exports = init();
} else {
//traditional namespace
context.PubSub = init();
}
}(this));