Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
E.Azer Koçulu
committed
Jan 15, 2014
1 parent
25193c8
commit 199573f
Showing
3 changed files
with
372 additions
and
192 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,146 +1,112 @@ | ||
module.exports = PubSub; | ||
module.exports = n; | ||
|
||
function PubSub(mix){ | ||
function n (mix) { | ||
var subscribers; | ||
var subscribersForOnce; | ||
|
||
var proxy = mix || function pubsubProxy(){ | ||
arguments.length && sub.apply(undefined, arguments); | ||
}; | ||
mix || (mix = function (fn) { | ||
if (fn) mix.subscribe(fn); | ||
}); | ||
|
||
function sub(callback){ | ||
subscribe(proxy, callback); | ||
} | ||
mix.subscribe = function (fn) { | ||
if (!subscribers) return subscribers = fn; | ||
if (typeof subscribers == 'function') subscribers = [subscribers]; | ||
subscribers.push(fn); | ||
}; | ||
|
||
function subOnce(callback){ | ||
once(proxy, callback); | ||
} | ||
mix.subscribe.once = function (fn) { | ||
if (!subscribersForOnce) return subscribersForOnce = fn; | ||
if (typeof subscribersForOnce == 'function') subscribersForOnce = [subscribersForOnce]; | ||
subscribersForOnce.push(fn); | ||
}; | ||
|
||
function unsubOnce(callback){ | ||
unsubscribeOnce(proxy, callback); | ||
} | ||
mix.unsubscribe = function (fn) { | ||
if (!subscribers) return; | ||
|
||
function unsub(callback){ | ||
unsubscribe(proxy, callback); | ||
} | ||
if (typeof subscribers == 'function') { | ||
if (subscribers != fn) return; | ||
subscribers = undefined; | ||
return; | ||
} | ||
|
||
function pub(){ | ||
var args = [proxy]; | ||
Array.prototype.push.apply(args, arguments); | ||
publish.apply(undefined, args); | ||
} | ||
var i = subscribers.length; | ||
|
||
proxy.subscribers = []; | ||
proxy.subscribersForOnce = []; | ||
while (i--) { | ||
if (subscribers[i] && subscribers[i] == fn){ | ||
subscribers[i] = undefined; | ||
return; | ||
} | ||
} | ||
}; | ||
|
||
proxy.subscribe = sub; | ||
proxy.subscribe.once = subOnce; | ||
proxy.unsubscribe = unsub; | ||
proxy.unsubscribe.once = unsubOnce; | ||
proxy.publish = pub; | ||
mix.unsubscribe.once = function (fn) { | ||
if (!subscribersForOnce) return; | ||
|
||
return proxy; | ||
} | ||
if (typeof subscribersForOnce == 'function') { | ||
if (subscribersForOnce != fn) return; | ||
subscribersForOnce = undefined; | ||
return; | ||
} | ||
|
||
/** | ||
* Publish "from" by applying given args | ||
* | ||
* @param {Function} from | ||
* @param {...Any} args | ||
*/ | ||
function publish(from){ | ||
var i = subscribersForOnce.length; | ||
|
||
var args = Array.prototype.slice.call(arguments, 1); | ||
while (i--) { | ||
if (subscribersForOnce[i] && subscribersForOnce[i] == fn){ | ||
subscribersForOnce[i] = undefined; | ||
return; | ||
} | ||
} | ||
}; | ||
|
||
if (from && from.subscribers && from.subscribers.length > 0) { | ||
from.subscribers.forEach(function(cb, i){ | ||
if(!cb) return; | ||
mix.publish = function () { | ||
var params = arguments; | ||
var i, len; | ||
|
||
try { | ||
cb.apply(undefined, args); | ||
} catch(exc) { | ||
setTimeout(function(){ throw exc; }, 0); | ||
} | ||
}); | ||
} | ||
if (subscribers && typeof subscribers != 'function' && subscribers.length) { | ||
i = -1; | ||
len = subscribers.length; | ||
|
||
var callbacks; | ||
if (from && from.subscribersForOnce && from.subscribersForOnce.length > 0) { | ||
callbacks = from.subscribersForOnce.splice(0, from.subscribersForOnce.length); | ||
callbacks.forEach(function(cb, i){ | ||
if(!cb) return; | ||
while (++i < len) { | ||
if (!subscribers[i] || typeof subscribers[i] != 'function') continue; | ||
|
||
try { | ||
subscribers[i].apply(undefined, params); | ||
} catch(err) { | ||
setTimeout(function () { throw err; }, 0); | ||
} | ||
}; | ||
} else if (typeof subscribers == 'function') { | ||
try { | ||
cb.apply(undefined, args); | ||
} catch(exc) { | ||
setTimeout(function(){ throw exc; }, 0); | ||
subscribers.apply(undefined, params); | ||
} catch(err) { | ||
setTimeout(function () { throw err; }, 0); | ||
} | ||
}); | ||
delete callbacks; | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Subscribe callback to given pubsub object. | ||
* | ||
* @param {Pubsub} to | ||
* @param {Function} callback | ||
*/ | ||
function subscribe(to, callback){ | ||
if(!callback) return false; | ||
return to.subscribers.push(callback); | ||
} | ||
|
||
|
||
/** | ||
* Subscribe callback to given pubsub object for only one publish. | ||
* | ||
* @param {Pubsub} to | ||
* @param {Function} callback | ||
*/ | ||
function once(to, callback){ | ||
if(!callback) return false; | ||
|
||
return to.subscribersForOnce.push(callback); | ||
} | ||
|
||
/** | ||
* Unsubscribe callback to given pubsub object. | ||
* | ||
* @param {Pubsub} to | ||
* @param {Function} callback | ||
*/ | ||
function unsubscribe(to, callback){ | ||
var i = to.subscribers.length; | ||
|
||
while(i--){ | ||
if(to.subscribers[i] && to.subscribers[i] == callback){ | ||
to.subscribers[i] = undefined; | ||
|
||
return i; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
if (subscribersForOnce && typeof subscribersForOnce != 'function' && subscribersForOnce.length) { | ||
i = -1; | ||
len = subscribersForOnce.length; | ||
|
||
/** | ||
* Unsubscribe callback subscribed for once to specified pubsub. | ||
* | ||
* @param {Pubsub} to | ||
* @param {Function} callback | ||
* @return {Boolean or Number} | ||
*/ | ||
function unsubscribeOnce(to, callback){ | ||
var i = to.subscribersForOnce.length; | ||
while (++i < len) { | ||
if (!subscribersForOnce[i] || typeof subscribersForOnce[i] != 'function') continue; | ||
|
||
while(i--){ | ||
if(to.subscribersForOnce[i] && to.subscribersForOnce[i] == callback){ | ||
to.subscribersForOnce[i] = undefined; | ||
try { | ||
subscribersForOnce[i].apply(undefined, params); | ||
} catch(err) { | ||
setTimeout(function () { throw err; }, 0); | ||
} | ||
}; | ||
|
||
return i; | ||
subscribersForOnce = undefined; | ||
} else if (typeof subscribersForOnce == 'function') { | ||
try { | ||
subscribersForOnce.apply(undefined, params); | ||
} catch(err) { | ||
setTimeout(function () { throw err; }, 0); | ||
} | ||
subscribersForOnce = undefined; | ||
} | ||
} | ||
}; | ||
|
||
return false; | ||
return mix; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
var pubsub = require('./'); | ||
|
||
it('subscribes and publishes', function(done){ | ||
var foo = pubsub(); | ||
|
||
foo.subscribe(function () { done(); }); | ||
|
||
foo.publish(3, 1, 4); | ||
}); | ||
|
||
it('adds multiple subscriptions', function(done){ | ||
var foo = pubsub(); | ||
|
||
foo.subscribe(function () {}); | ||
foo.subscribe(function () {}); | ||
foo.subscribe(function () { done(); }); | ||
|
||
foo.publish(3, 1, 4); | ||
}); | ||
|
||
it('subscribes and unsubscribes', function(){ | ||
var foo = pubsub(); | ||
foo.subscribe(foo); | ||
foo.unsubscribe(foo); | ||
|
||
function foo () {} | ||
}); |
Oops, something went wrong.