-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathpubsub.js
182 lines (165 loc) · 5.02 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
171
172
173
174
175
176
177
178
179
180
181
182
/**
* 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 (pubsubContext) {
/**
* @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
var subs = channels[args[0]];
var len;
var params;
var x;
if (subs) {
len = subs.length;
params = (args.length > 1) ?
Array.prototype.splice.call(args, 1) : [];
//console.log("dex.bus.publish: this=");
//console.dir(this);
//run the callbacks asynchronously,
//do not block the main execution process
var that = this;
setTimeout(
function () {
//executes callbacks in the order
//in which they were registered
for (x = 0; x < len; x += 1) {
// Take on pubsubContext of caller.
// REM: Seems to fix a memory leak; otherwise the scope of any subscribers
// is window by default due to dex.bus being in window pubsubContext.
subs[x].apply(that, params);
//subs[x].apply(pubsubContext, params);
}
//clear references to allow garbage collection
subs = undefined;
pubsubContext = undefined;
params = undefined;
},
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) {
//console.log("PUBSUB: SUBSCRIBE(CHANNEL, CALLBACK, THIS)");
//console.dir(channel);
//console.dir(callback);
//console.dir(this);
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
pubsubContext.PubSub = init();
}
}(this));