eventual-channel.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /** Concept each channel can have child channels ??**/
  2. const chs = ':'; // Channel separator
  3. class XEvent {
  4. constructor(donecb,args) {
  5. this.count = 0;
  6. this.dowait = 0;
  7. this.done= donecb; // Callback
  8. this.errors = [];
  9. this.params = args;
  10. }
  11. wait() {
  12. this.dowait = 1;
  13. }
  14. }
  15. class EventualChannel {
  16. constructor(eventual, name,parent) {
  17. this.eventual = eventual;
  18. this.name = name;
  19. this.parent = parent; //?? we need
  20. this.childs = {}
  21. this.listeners = [];
  22. }
  23. // createChannel based on name
  24. //
  25. fullName() {
  26. var name = this.name;
  27. for(var cur = this;cur = cur.parent;cur.parent) {
  28. if(this.parent.parent) { // if not root
  29. name = this.parent.name +":" + name;
  30. }
  31. }
  32. return name;
  33. }
  34. get2(name,create) {
  35. if(name == undefined) return this;
  36. var cur = this;
  37. var [childName,...sub] = name.split(chs);
  38. if(cur.child[childName] == undefined) {
  39. if(!create) return null;
  40. cur.child[name] = new EventualChannel(this.eventual,name,this);
  41. }
  42. return this.get2(sub.join(chs),create);
  43. };
  44. // Should be private function
  45. get(name,create) {
  46. // How it should work?
  47. // Recursivelly get a listener why? because of match
  48. var nodes = name.split(chs);
  49. var cur = this;
  50. var ok = 1;
  51. nodes.forEach((v) => {
  52. if( cur.childs[v] == undefined) {
  53. if(create == undefined) { ok = false; return null; }
  54. cur.childs[v] = new EventualChannel(this.eventual,name,this);
  55. }
  56. cur = cur.childs[v]; // next;
  57. });
  58. if(!ok) return null;
  59. return cur;
  60. }
  61. channel(name) { // Will create channel and return new child channel
  62. return this.get(name,true);
  63. }
  64. // Get listeners
  65. search(name,create) {
  66. var channel = this.get(name,create);
  67. if(channel) return channel.listeners;
  68. return [];
  69. }
  70. // Registers
  71. // new listener
  72. on (name,cb,order) {
  73. var channel = this.channel(name);
  74. var listener = { name:name, callback:cb, order: order || 0 };
  75. channel.listeners.push(listener)
  76. // Check for state call
  77. var cname = channel.fullName();
  78. if(this.eventual._events.state[cname]!=undefined) {
  79. this.process([listener],this.eventual._events.state[cname]);
  80. }
  81. return this;
  82. }
  83. emit(name,args) {
  84. var tocall = this.search(name);
  85. return this.process(tocall,args);
  86. }
  87. //TODO: CLEAN THIS
  88. /*
  89. * Basically process a list of functions and calls done in end
  90. * */
  91. process(tocall,nargs) {
  92. var self=this;
  93. var args = nargs || []; // or empty
  94. // Common for all for now
  95. var evt = new XEvent(next,args);
  96. var callback,dotrigger = 0;
  97. //Inner trigger
  98. // Finish
  99. function triggerDone() {
  100. if(callback) callback(evt);
  101. dotrigger = 1;
  102. }
  103. // Mem leak???
  104. var ret = {
  105. done: function(cb) {
  106. if(dotrigger) { cb(evt); }
  107. callback = cb;
  108. }
  109. }
  110. //this.stat.emitted++;
  111. // Sort
  112. tocall = tocall.sort((a,b) => {
  113. return (a.order - b.order)
  114. });
  115. // Get iter and setup evt
  116. var iter = tocall[Symbol.iterator]();
  117. function next() {
  118. process.nextTick(() => chain(iter));
  119. }
  120. // Internal thing
  121. function chain(iter) {
  122. // Stack overflow risk? maybe put this in process.tick();
  123. var v = iter.next();
  124. if(v.done) {
  125. triggerDone(); // Done callback with evt only
  126. return;
  127. }
  128. // Create evt here with some global event chaining iteraction
  129. try {
  130. var entry = v.value;
  131. evt.args = args;
  132. evt.name = entry.name;
  133. //self.stat.called++;
  134. entry.callback(...args,evt);
  135. evt.count++;
  136. }catch(e) {
  137. console.log(e);
  138. evt.errors.push(e);
  139. // Should we stop??
  140. }
  141. if(!evt.dowait) next();
  142. evt.dowait=0; // reset wait?
  143. }
  144. next();
  145. return ret;
  146. }
  147. }
  148. module.exports = EventualChannel;