|
@@ -0,0 +1,171 @@
|
|
|
+/** 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;
|