Permalink
Browse files

Merge pull request #1 from kriskowal/returns-unsubscribe

Return `off` from `on`
  • Loading branch information...
2 parents 188ae0a + 7c23406 commit c10db80e732b9a439aec4eca8fe2f7cd2fd52911 @domenic committed Nov 27, 2012
Showing with 52 additions and 9 deletions.
  1. +21 −6 lib/emitter.js
  2. +31 −3 test/1 basicFunctionality.coffee
View
@@ -7,6 +7,7 @@ function isHash(unknown) {
var SEPARATOR = " ";
module.exports = function emitter(normalListeners, oneTimeListeners, events) {
+
function subscribeSingleListener(eventName, listener, listeners) {
if (events && events.indexOf(eventName) === -1) {
throw new Error('Tried to subscribe to an unknown event "' + eventName + '".');
@@ -17,12 +18,19 @@ module.exports = function emitter(normalListeners, oneTimeListeners, events) {
}
listeners.get(eventName).push(listener);
+
+ return function unsubscribe() {
+ unsubscribeSingleListener(eventName, listener, listeners);
+ };
}
function subscribeMultipleListeners(hash, listeners) {
Object.keys(hash).forEach(function (eventName) {
subscribeSingleListener(eventName, hash[eventName], listeners);
});
+ return function unsubscribe() {
+ unsubscribeMultipleListeners(hash, listeners);
+ };
}
function unsubscribeSingleListener(eventName, listener, listeners) {
@@ -50,7 +58,7 @@ module.exports = function emitter(normalListeners, oneTimeListeners, events) {
throw new TypeError("hash argument must be a string-to-function hash.");
}
- subscribeMultipleListeners(eventNameOrHash, listeners);
+ return subscribeMultipleListeners(eventNameOrHash, listeners);
} else {
if (typeof eventNameOrHash !== "string") {
throw new TypeError("eventName argument must be a string.");
@@ -59,18 +67,25 @@ module.exports = function emitter(normalListeners, oneTimeListeners, events) {
throw new TypeError("listener argument must be a function.");
}
- eventNameOrHash.split(SEPARATOR).forEach(function (eventName) {
- subscribeSingleListener(eventName, listener, listeners);
+ var unsubscribers = eventNameOrHash.split(SEPARATOR)
+ .map(function (eventName) {
+ return subscribeSingleListener(eventName, listener, listeners);
});
+
+ return function unsubscribe() {
+ unsubscribers.forEach(function (unsubscribe) {
+ unsubscribe();
+ });
+ };
}
}
-
+
return {
on: function (eventNameOrHash, listener) {
- onImpl(eventNameOrHash, listener, normalListeners);
+ return onImpl(eventNameOrHash, listener, normalListeners);
},
onNext: function (eventNameOrHash, listener) {
- onImpl(eventNameOrHash, listener, oneTimeListeners);
+ return onImpl(eventNameOrHash, listener, oneTimeListeners);
},
off: function (eventNameOrHash, listener) {
if (typeof eventNameOrHash === "string") {
@@ -10,10 +10,11 @@ describe "Publisher/emitter under normal usage", ->
describe "when an event has been subscribed to", ->
listener = null
+ unsubscribe = null
beforeEach ->
listener = sinon.spy()
- emitter.on("eventName", listener)
+ unsubscribe = emitter.on("eventName", listener)
it "should call the subscribing listener when the event is published", ->
publisher.publish("eventName")
@@ -36,6 +37,12 @@ describe "Publisher/emitter under normal usage", ->
listener.should.not.have.been.called
+ it "should not call the listener when publishing after unsubscribing with the function 'on' returns", ->
+ unsubscribe()
+ publisher.publish("eventName")
+
+ listener.should.not.have.been.called
+
describe "when an event has been subscribed to twice by the same listener", ->
listener = null
@@ -102,10 +109,11 @@ describe "Publisher/emitter under normal usage", ->
describe "when three events are subscribed to in one call", ->
events = ["event1", "event2", "event3"]
listener = null
+ unsubscribe = null
beforeEach ->
listener = sinon.spy()
- emitter.on(events.join(" "), listener)
+ unsubscribe = emitter.on(events.join(" "), listener)
it "publishes the first event correctly", ->
publisher.publish("event1")
@@ -136,15 +144,23 @@ describe "Publisher/emitter under normal usage", ->
listener.should.not.have.been.called
+ it "unsubscribes from two events at once, when calling the returned unsubscriber", ->
+ unsubscribe()
+ publisher.publish("event2")
+ publisher.publish("event3")
+
+ listener.should.not.have.been.called
+
describe "when a hash object mapping event names to listeners is used for subscription", ->
hash = null
+ unsubscribe = null
beforeEach ->
hash =
event1: sinon.spy()
event2: sinon.spy()
event3: sinon.spy()
- emitter.on(hash)
+ unsubscribe = emitter.on(hash)
it "publishes events correctly", ->
publisher.publish("event1")
@@ -164,3 +180,15 @@ describe "Publisher/emitter under normal usage", ->
hash.event1.should.not.have.been.called
hash.event2.should.not.have.been.called
hash.event3.should.not.have.been.called
+
+ it "does not publish events when they are unsubscribed with the returned function", ->
+ unsubscribe()
+
+ publisher.publish("event1")
+ publisher.publish("event2")
+ publisher.publish("event3")
+
+ hash.event1.should.not.have.been.called
+ hash.event2.should.not.have.been.called
+ hash.event3.should.not.have.been.called
+

0 comments on commit c10db80

Please sign in to comment.