123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- /** 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;
|