/** Concept each channel can have child channels ??**/ const chs = ':'; // Channel separator 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 EventualChannel { constructor(eventual, name,parent) { this.eventual = eventual; this.name = name; this.parent = parent; //?? we need this.childs = {} this.listeners = []; } // createChannel based on name // fullName() { var name = this.name; for(var cur = this;cur = cur.parent;cur.parent) { if(this.parent.parent) { // if not root name = this.parent.name +":" + name; } } return name; } get2(name,create) { if(name == undefined) return this; var cur = this; var [childName,...sub] = name.split(chs); if(cur.child[childName] == undefined) { if(!create) return null; cur.child[name] = new EventualChannel(this.eventual,name,this); } return this.get2(sub.join(chs),create); }; // Should be private function get(name,create) { // How it should work? // Recursivelly get a listener why? because of match var nodes = name.split(chs); var cur = this; var ok = 1; nodes.forEach((v) => { if( cur.childs[v] == undefined) { if(create == undefined) { ok = false; return null; } cur.childs[v] = new EventualChannel(this.eventual,name,this); } cur = cur.childs[v]; // next; }); if(!ok) return null; return cur; } channel(name) { // Will create channel and return new child channel return this.get(name,true); } // Get listeners search(name,create) { var channel = this.get(name,create); if(channel) return channel.listeners; return []; } // Registers // new listener on (name,cb,order) { var channel = this.channel(name); var listener = { name:name, callback:cb, order: order || 0 }; channel.listeners.push(listener) // Check for state call var cname = channel.fullName(); if(this.eventual._events.state[cname]!=undefined) { this.process([listener],this.eventual._events.state[cname]); } return this; } emit(name,args) { var tocall = this.search(name); return this.process(tocall,args); } //TODO: CLEAN THIS /* * Basically process a list of functions and calls done in end * */ process(tocall,nargs) { var self=this; var args = nargs || []; // or empty // Common for all for now var evt = new XEvent(next,args); var callback,dotrigger = 0; //Inner trigger // Finish function triggerDone() { if(callback) callback(evt); dotrigger = 1; } // Mem leak??? var ret = { done: function(cb) { if(dotrigger) { cb(evt); } callback = cb; } } //this.stat.emitted++; // Sort tocall = tocall.sort((a,b) => { return (a.order - b.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) { triggerDone(); // Done callback with evt only return; } // Create evt here with some global event chaining iteraction try { var entry = v.value; evt.args = args; evt.name = entry.name; //self.stat.called++; entry.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(); return ret; } } module.exports = EventualChannel;