-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Events have been rewritten and moved inside of modules * Adds event tests Improves emit argument handling Adds default data to end of all emits * Fixed prepArgs * Handles array and string based namespacing * Fixed typo
- Loading branch information
Showing
5 changed files
with
230 additions
and
57 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
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,142 @@ | ||
'use strict'; | ||
|
||
/** | ||
* Allows MeanIO to create a unique wrapper for a single EventEmitter per Module. | ||
* With this, we allows all Modules to use the same EventEmitter, but automatically | ||
* namespace their events with the module name. | ||
*/ | ||
|
||
var delimiter = '.'; | ||
var EventEmitter2 = require('eventemitter2').EventEmitter2; | ||
var emitter = new EventEmitter2({ | ||
wildcard: true, | ||
delimiter: delimiter, | ||
// set this to `true` if you want to emit the newListener event. The default value is `true` | ||
newListener: true, | ||
// the maximum amount of listeners that can be assigned to an event, default 10. | ||
maxListeners: 20 | ||
}); | ||
|
||
/** | ||
* @param {string} name - Name of the module, used to namespace events | ||
* @constructor | ||
*/ | ||
function Events(name) { | ||
this.name = name; | ||
this._default = {}; | ||
} | ||
|
||
/** | ||
* Emits an event for the module | ||
* Automatically namespaced with the moduleName passed to the constructor | ||
* @deprecated Use emit with EventEmitter2 standard api | ||
* @param {*} opts - Any data to be passed with the event | ||
* @param {string} opts.action - Name of the event that happesn | ||
*/ | ||
Events.prototype.publish = function (opts) { | ||
console.error('publish() has been deprecated. Update to emit(event, data).'); | ||
|
||
if (!opts.action) { | ||
console.error('Error: events require an "action" property'); | ||
return; | ||
} | ||
this.emit([this.name, opts.action], opts); | ||
}; | ||
|
||
/** | ||
* Calls emit with the module name as the default root namespace | ||
* @see EventEmitter2.emit | ||
* @link https://github.com/asyncly/EventEmitter2 | ||
* @param {array|string} event | ||
* @return {boolean} | ||
*/ | ||
Events.prototype.emit = function (event) { | ||
var args = prepArgs(arguments, this.name, event, this._default); | ||
return emitter.emit.apply(emitter, args); | ||
}; | ||
|
||
/** | ||
* Calls emitAsync with the module name as the default root namespace | ||
* @see EventEmitter2.emitAsync | ||
* @link https://github.com/asyncly/EventEmitter2 | ||
* @param event | ||
* @returns {Promise} | ||
*/ | ||
Events.prototype.emitAsync = function (event) { | ||
var args = prepArgs(arguments, this.name, event, this._default); | ||
return emitter.emitAsync.apply(emitter, args); | ||
}; | ||
|
||
/** | ||
* @deprecated | ||
* @param {string|array} name - Event name | ||
* @param {function} cb | ||
*/ | ||
Events.prototype.subscribe = function (name, cb) { | ||
console.error('subscribe() has been deprecated. Update to on(event, listener)'); | ||
this.on(name, cb); | ||
}; | ||
|
||
/** | ||
* Sets defaults that will be included with every event | ||
* Individual keys are overwritten if passed to emit() | ||
* @param data | ||
*/ | ||
Events.prototype.setDefaults = function (data) { | ||
for (var index in data) { | ||
this._default[index] = data[index]; | ||
} | ||
}; | ||
|
||
/** | ||
* @deprecated Use setDefaults | ||
* @param {*} data | ||
*/ | ||
Events.prototype.defaultData = function (data) { | ||
console.error('defaultData() has been deprecated. Update to setDefaults(data)'); | ||
this.setDefaults(data); | ||
}; | ||
|
||
/** | ||
* Extending EventEmitter2 API | ||
*/ | ||
Events.prototype.addListener = emitter.addListener.bind(emitter); | ||
Events.prototype.on = emitter.on.bind(emitter); | ||
Events.prototype.onAny = emitter.onAny.bind(emitter); | ||
Events.prototype.offAny = emitter.offAny.bind(emitter); | ||
Events.prototype.once = emitter.once.bind(emitter); | ||
Events.prototype.many = emitter.many.bind(emitter); | ||
Events.prototype.removeListener = emitter.removeListener.bind(emitter); | ||
Events.prototype.off = emitter.off.bind(emitter); | ||
Events.prototype.removeAllListeners = emitter.removeAllListeners.bind(emitter); | ||
Events.prototype.setMaxListeners = emitter.setMaxListeners.bind(emitter); | ||
Events.prototype.listeners = emitter.listeners.bind(emitter); | ||
Events.prototype.listenersAny = emitter.listenersAny.bind(emitter); | ||
|
||
module.exports = Events; | ||
|
||
/** | ||
* Helps in preparing our arguments for passing to emit and emitAsync | ||
* @param args | ||
* @param name | ||
* @param defaults | ||
* @returns {*} | ||
*/ | ||
function prepArgs(args, name, event, defaults) { | ||
args = Array.from(args); | ||
|
||
var namespace = [name]; | ||
if (!Array.isArray(event)) { | ||
event = event.split(delimiter); | ||
} | ||
|
||
namespace = namespace.concat(event); | ||
|
||
args.shift();//remove the event | ||
|
||
args.unshift(namespace); | ||
if (defaults) { | ||
args.push(defaults); | ||
} | ||
return args; | ||
} |
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
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 |
---|---|---|
|
@@ -46,4 +46,3 @@ describe('MEAN IO Core', function () { | |
}); | ||
}); | ||
}); | ||
|
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,87 @@ | ||
'use strict'; | ||
/* jshint -W024 */ | ||
/* jshint expr:true */ | ||
|
||
var chai = require('chai'), | ||
expect = chai.expect; | ||
require('mocha-sinon'); | ||
|
||
var Events = require('../../../lib/core_modules/module/events.js'); | ||
|
||
describe('Module Events', function () { | ||
var e1 = new Events('one'); | ||
var e2 = new Events('two'); | ||
var listener; | ||
|
||
beforeEach(function () { | ||
listener = this.sinon.stub(); | ||
listener.reset(); | ||
}); | ||
|
||
it('should have all EventEmitter2 functions', function () { | ||
expect(e1.addListener).to.exist; | ||
expect(e1.on).to.exist; | ||
expect(e1.onAny).to.exist; | ||
expect(e1.offAny).to.exist; | ||
expect(e1.once).to.exist; | ||
expect(e1.many).to.exist; | ||
expect(e1.removeListener).to.exist; | ||
expect(e1.off).to.exist; | ||
expect(e1.removeAllListeners).to.exist; | ||
expect(e1.setMaxListeners).to.exist; | ||
expect(e1.listeners).to.exist; | ||
expect(e1.listenersAny).to.exist; | ||
}); | ||
|
||
describe('Namespacing', function () { | ||
it('should use name', function () { | ||
e1.on([e1.name, 'test'], listener); | ||
e1.emit('test'); | ||
expect(listener.calledOnce).to.be.true; | ||
}); | ||
|
||
it('should allow .on across namespaces', function () { | ||
e1.on([e2.name, 'test'], listener); | ||
e2.emit('test'); | ||
expect(listener.calledOnce).to.be.true; | ||
}); | ||
|
||
it('should work with arrays', function() { | ||
e1.on([e1.name, 'ns', 'array'], listener); | ||
e1.emit(['ns', 'array']); | ||
expect(listener.calledOnce).to.be.true; | ||
}); | ||
|
||
it('should work with arrays and strings', function(){ | ||
e1.on([e1.name, 'array', 'string'], listener); | ||
e1.emit('array.string'); | ||
expect(listener.calledOnce).to.be.true; | ||
}); | ||
|
||
it('should work with strings and arrays', function(){ | ||
e1.on(e1.name + '.string.array', listener); | ||
e1.emit(['string', 'array']); | ||
expect(listener.calledOnce).to.be.true; | ||
}); | ||
}); | ||
|
||
describe('Default Data', function () { | ||
var def = {test: true}; | ||
it('should send default data', function () { | ||
e1.setDefaults(def); | ||
e1.on('one.default', listener); | ||
e1.emit('default'); | ||
expect(listener.calledOnce).to.be.true; | ||
expect(listener.calledWith(def)).to.be.true; | ||
}); | ||
|
||
it('should append default data to end of array', function(){ | ||
var obj = {}; | ||
e1.setDefaults(def); | ||
e1.on('one.default.append', listener); | ||
e1.emit('default.append', obj); | ||
expect(listener.calledOnce).to.be.true; | ||
expect(listener.calledWith(obj, def)).to.be.true; | ||
}) | ||
}); | ||
}); |