Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * @module
- */
- import { EventEmitter } from "events";
- import { expect } from "chai";
- import uuid from "uuid/v4";
- import { PausableTimer } from "./timer";
- /**
- * Custom extended event emitter.
- *
- * @class
- */
- class EEmitter extends EventEmitter {};
- /**
- * Connector.
- *
- * @class
- * @example
- *
- * import { connect } from "connect";
- *
- * var obj0 = {
- * func: () => console.log("hello"),
- * };
- *
- * var obj1 = {
- * func: () => console.log("hello"),
- * };
- *
- * var obj2 = {
- * func: () => console.log("world"),
- * };
- *
- * var obj3 = {
- * func: () => console.log("again"),
- * };
- *
- * connect(obj0, "func", obj2, "func");
- * obj0.func(); # -> hello world
- *
- * connect(obj1, "func", null, () => {
- * obj2.func();
- * obj3.func();
- * });
- * obj1.func(); # -> hello world again
- *
- */
- class Connector {
- /**
- * Connector constructor.
- *
- * @method
- * @param {number} [polling=1] - Interval to poll `pause` status, ms.
- */
- constructor (polling = 1) {
- this.ee = new EEmitter();
- this.id = uuid();
- this.paused = false;
- this.polling = polling;
- this.t = new PausableTimer(polling = this.polling);
- };
- /**
- * Connect emitter signal with receiver slot.
- *
- * Alert:
- * Despite of it supports subscription before signal execution
- * (`type="start"`), due to `JavaScript` async behaviour event execution
- * will happen after signal execution (in next tick). Potentially it may
- * call signal in `process.nextTick`, but now it's not actual, because
- * often case to use subscription after signal execution.
- *
- * @method
- * @param {object} emitter - Object which emits signal.
- * @param {string} signal - Name of emitter method on which event will be
- * emitted.
- * @param {?object} receiver - Object which receives signal event or `null`.
- * @param {string|function} slot - Name of receiver method or function
- * which will be executed on signal event.
- * @param {string} [type=end] - When signal to receiver happens. Supported
- * values are `end` (most frequent), `start`, `both`.
- * @param {?number} [timeout=null] - Time to postpone slot execution.
- */
- connect (emitter, signal, receiver, slot, type = "end", timeout = null) {
- expect([ "start", "end", "both" ],
- "Invalid argument 'type'").to.include(type);
- let self = this;
- slot = slot instanceof Function ? slot : receiver[slot];
- let eName = (emitter.instanceName || uuid()) + "." + signal;
- let origFunc = emitter[signal];
- let start = origFunc.__start || (eName + " start");
- let end = origFunc.__end || (eName + " end");
- if ([ "start", "both" ].includes(type)) {
- self.ee.on(start, args => slot.apply(receiver, args));
- };
- if ([ "end", "both" ].includes(type)) {
- self.ee.on(end, args => slot.apply(receiver, args));
- };
- if (!origFunc.__emittable) {
- origFunc.__emittable = [];
- };
- if (origFunc.__emittable.includes(self.id)) {
- return;
- };
- let fn;
- if (timeout) {
- fn = cb => self.t.setTimeout(cb, timeout);
- } else {
- fn = cb => cb();
- };
- let emit = cb => {
- if (self.paused) {
- var timerId = setInterval(() => {
- if (self.paused) return;
- clearInterval(timerId);
- fn(cb);
- }, self.polling);
- } else {
- fn(cb);
- };
- };
- emitter[signal] = function () {
- emit(() => self.ee.emit(start, arguments));
- let result = origFunc.apply(this, arguments);
- emit(() => self.ee.emit(end, arguments));
- return result;
- };
- emitter[signal].__emittable = origFunc.__emittable;
- emitter[signal].__emittable.push(self.id);
- emitter[signal].__start = start;
- emitter[signal].__end = end;
- };
- /**
- * Pauses connector.
- *
- * @method
- */
- pause () {
- this.paused = true;
- this.t.pause();
- };
- /**
- * Resumes connector.
- *
- * @method
- */
- resume () {
- this.paused = false;
- thi.t.resume();
- };
- };
- let c = new Connector();
- let connect = c.connect.bind(c);
- connect.pause = c.pause.bind(c);
- connect.resume = c.resume.bind(c);
- export { connect, Connector };
Add Comment
Please, Sign In to add comment