Guest User

Untitled

a guest
Oct 23rd, 2017
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.42 KB | None | 0 0
  1. /**
  2. * @module
  3. */
  4.  
  5. import { EventEmitter } from "events";
  6. import { expect } from "chai";
  7. import uuid from "uuid/v4";
  8.  
  9. import { PausableTimer } from "./timer";
  10. /**
  11. * Custom extended event emitter.
  12. *
  13. * @class
  14. */
  15. class EEmitter extends EventEmitter {};
  16. /**
  17. * Connector.
  18. *
  19. * @class
  20. * @example
  21. *
  22. * import { connect } from "connect";
  23. *
  24. * var obj0 = {
  25. * func: () => console.log("hello"),
  26. * };
  27. *
  28. * var obj1 = {
  29. * func: () => console.log("hello"),
  30. * };
  31. *
  32. * var obj2 = {
  33. * func: () => console.log("world"),
  34. * };
  35. *
  36. * var obj3 = {
  37. * func: () => console.log("again"),
  38. * };
  39. *
  40. * connect(obj0, "func", obj2, "func");
  41. * obj0.func(); # -> hello world
  42. *
  43. * connect(obj1, "func", null, () => {
  44. * obj2.func();
  45. * obj3.func();
  46. * });
  47. * obj1.func(); # -> hello world again
  48. *
  49. */
  50. class Connector {
  51. /**
  52. * Connector constructor.
  53. *
  54. * @method
  55. * @param {number} [polling=1] - Interval to poll `pause` status, ms.
  56. */
  57. constructor (polling = 1) {
  58. this.ee = new EEmitter();
  59. this.id = uuid();
  60. this.paused = false;
  61. this.polling = polling;
  62. this.t = new PausableTimer(polling = this.polling);
  63. };
  64. /**
  65. * Connect emitter signal with receiver slot.
  66. *
  67. * Alert:
  68. * Despite of it supports subscription before signal execution
  69. * (`type="start"`), due to `JavaScript` async behaviour event execution
  70. * will happen after signal execution (in next tick). Potentially it may
  71. * call signal in `process.nextTick`, but now it's not actual, because
  72. * often case to use subscription after signal execution.
  73. *
  74. * @method
  75. * @param {object} emitter - Object which emits signal.
  76. * @param {string} signal - Name of emitter method on which event will be
  77. * emitted.
  78. * @param {?object} receiver - Object which receives signal event or `null`.
  79. * @param {string|function} slot - Name of receiver method or function
  80. * which will be executed on signal event.
  81. * @param {string} [type=end] - When signal to receiver happens. Supported
  82. * values are `end` (most frequent), `start`, `both`.
  83. * @param {?number} [timeout=null] - Time to postpone slot execution.
  84. */
  85. connect (emitter, signal, receiver, slot, type = "end", timeout = null) {
  86.  
  87. expect([ "start", "end", "both" ],
  88. "Invalid argument 'type'").to.include(type);
  89.  
  90. let self = this;
  91.  
  92. slot = slot instanceof Function ? slot : receiver[slot];
  93.  
  94. let eName = (emitter.instanceName || uuid()) + "." + signal;
  95. let origFunc = emitter[signal];
  96.  
  97. let start = origFunc.__start || (eName + " start");
  98. let end = origFunc.__end || (eName + " end");
  99.  
  100. if ([ "start", "both" ].includes(type)) {
  101. self.ee.on(start, args => slot.apply(receiver, args));
  102. };
  103. if ([ "end", "both" ].includes(type)) {
  104. self.ee.on(end, args => slot.apply(receiver, args));
  105. };
  106.  
  107. if (!origFunc.__emittable) {
  108. origFunc.__emittable = [];
  109. };
  110. if (origFunc.__emittable.includes(self.id)) {
  111. return;
  112. };
  113.  
  114. let fn;
  115. if (timeout) {
  116. fn = cb => self.t.setTimeout(cb, timeout);
  117. } else {
  118. fn = cb => cb();
  119. };
  120.  
  121. let emit = cb => {
  122. if (self.paused) {
  123. var timerId = setInterval(() => {
  124. if (self.paused) return;
  125. clearInterval(timerId);
  126. fn(cb);
  127. }, self.polling);
  128. } else {
  129. fn(cb);
  130. };
  131. };
  132.  
  133. emitter[signal] = function () {
  134. emit(() => self.ee.emit(start, arguments));
  135. let result = origFunc.apply(this, arguments);
  136. emit(() => self.ee.emit(end, arguments));
  137. return result;
  138. };
  139.  
  140. emitter[signal].__emittable = origFunc.__emittable;
  141. emitter[signal].__emittable.push(self.id);
  142. emitter[signal].__start = start;
  143. emitter[signal].__end = end;
  144. };
  145. /**
  146. * Pauses connector.
  147. *
  148. * @method
  149. */
  150. pause () {
  151. this.paused = true;
  152. this.t.pause();
  153. };
  154. /**
  155. * Resumes connector.
  156. *
  157. * @method
  158. */
  159. resume () {
  160. this.paused = false;
  161. thi.t.resume();
  162. };
  163. };
  164.  
  165. let c = new Connector();
  166. let connect = c.connect.bind(c);
  167. connect.pause = c.pause.bind(c);
  168. connect.resume = c.resume.bind(c);
  169.  
  170. export { connect, Connector };
Add Comment
Please, Sign In to add comment