123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- var log = require('hlogger').createLogger('xevents');
- class XPrefix {
- constructor(ctx,event,prefix) {
- this.ctx = ctx;
- this.event = event;
- this.prefix = prefix || "";
- }
- on(name,cb) {
- this.event.on(this.ctx,this.prefix + ":" + name, cb);
- return this;
- }
- }
- class XEvent {
- constructor(donecb,args) {
- this.count = 0;
- this.dowait = 0;
-
- this.done= donecb; // Callback
- this.errors = [];
- this.params = args;
- }
- wait() {
- this.dowait = 1;
- }
- }
- class XEventListener {
- constructor(ctx,name,cb,order) {
- this.ctx = ctx;
- this.name = name;
- this.callback = cb;
- this.order = order || 0; // Late call
- }
- }
- // Smarter event system?
- class XEventEmitter {
-
- constructor() {
- // Prepare this in a single context
- //this.listeners = new Map();
- this.listeners = [];
- this.auto = {};
- this.stat = {
- emitted:0,
- tried:0,
- called:0
- }
- }
- addListener(...args) {
- var ctx = this,evtName,cb,order;
- if(typeof(args[0]) == "string") {
- [evtName,cb,order] = args;
- } else {
- [ctx,evtName,cb,order] = args;
- }
- var listener = new XEventListener(ctx,evtName,cb,order);
- this.listeners.push(listener);
- //this.listeners.push(entry);
-
- // Process the autos
- var re = new RegExp(evtName);
- Object.keys(this.auto).map((v) => {
- var match = v.match(re);
- if(v.match(re)) {
- var tocall = [{match:match,listener:listener}];
- this.process(tocall,this.auto[v]); // No callback
- }
- });
-
- /* try {
- cb(this.auto[v], new XEvent());
- } catch(e) {
- console.log(e);
- }
- }
- });*/
- }
- // Remove listeners by ctx
- removeListener(ctx,name) {
- this.listeners = this.listeners.filter((v) => {
- if(v == ctx || v.ctx == ctx) {
- } else {
- return v;
- }
- });
- }
-
- // 1 arg only
- toggleOn(name,...args) {
- // Should be contextual if we remove context toggle will remain
- this.auto[name] = args; // should store array
- this.emit(name,...args);
- }
- toggleOff(name) {
- delete this.auto[name];
- }
- process(tocall,nargs,cb) {
- var self=this;
-
- var args = nargs || []; // or empty
- // Common for all for now
- var evt = new XEvent(next,args);
- this.stat.emitted++;
- // Sort
- tocall = tocall.sort((a,b) => {
- return (a.listener.order - b.listener.order)
- });
- // Get iter and setup evt
- var iter = tocall[Symbol.iterator]();
-
- function next() {
- process.nextTick(() => chain(iter));
- }
- // Internal thing
- function chain(iter) {
- // Stack overflow risk? maybe put this in process.tick();
- var v = iter.next();
- if(v.done) {
- if(cb != undefined) cb(evt); // Done callback with evt only
- return;
- }
- // Create evt here with some global event chaining iteraction
- try {
- var entry = v.value;
- evt.match = entry.match;
- evt.args = args;
- self.stat.called++;
- entry.listener.callback(...args,evt);
- evt.count++;
- }catch(e) {
- console.log(e);
- evt.errors.push(e);
- // Should we stop??
- }
- if(!evt.dowait) next();
- evt.dowait=0; // reset wait?
- }
- next();
- }
- search(name,ctx) {
- var ret = [];
- this.listeners.forEach((v) => {
- var re = new RegExp( "^" + v.name+ "$" );
- //var re = v.name;
- var matchres = name.match(re);
- if(matchres && (ctx == undefined || ctx == v.ctx) ) {
- ret.push({
- match: matchres,
- listener:v
- });
- }
- });
- return ret;
- }
- // Multiple argument
- // Should work like emit("event",1,2,3,4,5);
- emit(name,...args) {
- this.stat.tried++;
- var tocall = this.search(name);
- var evt,callback,dotrigger = 0;
- function trigger(ievt) {
- evt = ievt; // Will call
- if(callback)callback(evt);
- }
- // Mem leak???
- var ret = {
- done: function(cb) {
- if(evt) { cb(evt); }
- callback = cb;
- }
- }
- // Test
- this.process(tocall,args, trigger );
- return ret ;
- }
- // Why?
- /*emitTo(ctx,name,args) {
- var tocall = this.search(name,ctx)
- this.process(tocall,arg,cb);
- }*/
- // Alias
- on(ctx,match,cb) {
- this.addListener(ctx,match,cb);
- return this;
- }
- after(ctx,match,cb) {
- this.addListener(ctx,match,cb,1000);
- return this;
- }
- prefix(ctx,prefix) {
- return new XPrefix(ctx,this,prefix);
- }
- /*when(ctx,match,cb) {
- this.addListener(ctx,match,cb);
- }*/
- }
- module.exports=XEventEmitter;
|