Skip to content
Permalink
Browse files
Fix CB-3785
Enable support of EventListener interface for
Channel.prototype.subscribe / unsubscribe

 This closes #130
  • Loading branch information
rayshan authored and stevengill committed Oct 6, 2016
1 parent 62dd53f commit 81d8b9924b78804017fbce2ee7bd3f92560d341a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 20 deletions.
@@ -134,8 +134,13 @@ var Channel = function(type, sticky) {
}
};

function forceFunction(f) {
if (typeof f != 'function') throw "Function required as first argument!";
function checkSubscriptionArgument(argument) {
if (typeof argument !== "function" && typeof argument.handleEvent !== "function") {
throw new Error(
"Must provide a function or an EventListener object " +
"implementing the handleEvent interface."
);
}
}

/**
@@ -145,28 +150,39 @@ function forceFunction(f) {
* and a guid that can be used to stop subscribing to the channel.
* Returns the guid.
*/
Channel.prototype.subscribe = function(f, c) {
// need a function to call
forceFunction(f);
Channel.prototype.subscribe = function(eventListenerOrFunction, eventListener) {
checkSubscriptionArgument(eventListenerOrFunction);
var handleEvent, guid;

if (eventListenerOrFunction && typeof eventListenerOrFunction === "object") {
// Received an EventListener object implementing the handleEvent interface
handleEvent = eventListenerOrFunction.handleEvent;
eventListener = eventListenerOrFunction;
} else {
// Received a function to handle event
handleEvent = eventListenerOrFunction;
}

if (this.state == 2) {
f.apply(c || this, this.fireArgs);
handleEvent.apply(eventListener || this, this.fireArgs);
return;
}

var func = f,
guid = f.observer_guid;
if (typeof c == "object") { func = utils.close(c, f); }
guid = eventListenerOrFunction.observer_guid;
if (typeof eventListener === "object") {
handleEvent = utils.close(eventListener, handleEvent);
}

if (!guid) {
// first time any channel has seen this subscriber
// First time any channel has seen this subscriber
guid = '' + nextGuid++;
}
func.observer_guid = guid;
f.observer_guid = guid;
handleEvent.observer_guid = guid;
eventListenerOrFunction.observer_guid = guid;

// Don't add the same handler more than once.
if (!this.handlers[guid]) {
this.handlers[guid] = func;
this.handlers[guid] = handleEvent;
this.numHandlers++;
if (this.numHandlers == 1) {
this.onHasSubscribersChange && this.onHasSubscribersChange();
@@ -177,12 +193,20 @@ Channel.prototype.subscribe = function(f, c) {
/**
* Unsubscribes the function with the given guid from the channel.
*/
Channel.prototype.unsubscribe = function(f) {
// need a function to unsubscribe
forceFunction(f);
Channel.prototype.unsubscribe = function(eventListenerOrFunction) {
checkSubscriptionArgument(eventListenerOrFunction);
var handleEvent, guid, handler;

if (eventListenerOrFunction && typeof eventListenerOrFunction === "object") {
// Received an EventListener object implementing the handleEvent interface
handleEvent = eventListenerOrFunction.handleEvent;
} else {
// Received a function to handle event
handleEvent = eventListenerOrFunction;
}

var guid = f.observer_guid,
handler = this.handlers[guid];
guid = handleEvent.observer_guid;
handler = this.handlers[guid];
if (handler) {
delete this.handlers[guid];
this.numHandlers--;
@@ -36,7 +36,7 @@ describe("channel", function () {
});

describe("subscribe method", function() {
it("should throw an exception if no function is provided", function() {
it("should throw an exception if no arguments are provided", function() {
expect(function() {
multiChannel.subscribe();
}).toThrow();
@@ -48,6 +48,15 @@ describe("channel", function () {
expect(function() {
multiChannel.subscribe(undefined);
}).toThrow();
});
it("should accept a function or an EventListener object implementing the handleEvent interface", function() {
expect(function() {
multiChannel.subscribe(function () {});
}).not.toThrow();

expect(function() {
multiChannel.subscribe({handleEvent: function () {}});
}).not.toThrow();

expect(function() {
multiChannel.subscribe({apply:function(){},call:function(){}});
@@ -82,14 +91,28 @@ describe("channel", function () {
});

describe("unsubscribe method", function() {
it("should throw an exception if passed in null or undefined", function() {
it("should throw an exception if no arguments are provided", function() {
expect(function() {
multiChannel.unsubscribe();
}).toThrow();

expect(function() {
multiChannel.unsubscribe(null);
}).toThrow();
});
it("should accept a function or an EventListener object implementing the handleEvent interface", function() {
expect(function() {
multiChannel.unsubscribe(function () {});
}).not.toThrow();

expect(function() {
multiChannel.unsubscribe({handleEvent: function () {}});
}).not.toThrow();

expect(function() {
multiChannel.unsubscribe({apply:function(){},call:function(){}});
}).toThrow();
});
it("should not decrement numHandlers if unsubscribing something that does not exist", function() {
multiChannel.subscribe(function() {});
multiChannel.unsubscribe(function() {});

0 comments on commit 81d8b99

Please sign in to comment.