UNPKG

badmfck-signal

Version:

An implementation of a signaling mechanism used to connect components and transfer data between them

139 lines (138 loc) 4.64 kB
"use strict"; // T - request, // K - response var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Binder = void 0; const _1 = __importStar(require(".")); /** * * Binder provide functionality to bind data to any component * T - request type * K - data type * * To use Binder you need to create instance of it and provide request and response types * Use request() to send request to data source via request pipeline, anyone can subscribe to request pipeline * Use subscribe() to request data from source via response pipeline, anyone can subscribe to response pipeline * Use execute() to request data from source and wait for response * Use use() to bind data to react component, before using it you need to setup react hooks, by calling Binder.setupReact(useState,useEffect) * */ class Binder { static reactUseState = null; static reactUseEffect = null; static nextID = 0; name; type = "binder"; readyListener = new _1.default(); // OUT -> requestListener = new _1.default(); // IN <- constructor(name) { if (!name) name = "Binder_" + (Binder.nextID++); this.name = name; } /** * Setup react hook before using it * @param useState - reference to react useState * @param useEffect - reference to react useEffect */ static setupReact(useState, useEffect) { if (Binder.reactUseEffect && Binder.reactUseState) return; Binder.reactUseEffect = useEffect; Binder.reactUseState = useState; _1.default.setupReact(useState, useEffect); } /** subscribe to request pipeline */ onRequest(cb) { this.requestListener.subscribe(cb); } /** subscribe to response pipeline */ subscribe(cb) { this.readyListener.subscribe(cb); } /** invoke response pipeline */ invoke(data) { this.readyListener.invoke(data); } /* invoke request pipeline */ request(req) { this.requestListener.invoke(req); } /** Execute binder & wait for results */ async execute(req) { const cb = { resolve: null }; const promise = new Promise((resolve, reject) => { cb.resolve = resolve; }); const sh = new _1.SignalHandler(); sh.add(this.readyListener, data => { if (cb.resolve) cb.resolve(data); sh.clear(); }); this.requestListener.invoke(req ?? null); return promise; } /** * Binder hook * request - request object for data loading procedure * initial - initial data object * dependency - react dependency array * return - array [data,busy], where first element - Binded data, second element - Busy indicator */ use(request, initial, dependency) { const [data, setData] = Binder.reactUseState(initial ?? null); const [busy, setBusy] = Binder.reactUseState(false); Binder.reactUseEffect(() => { const sh = new _1.SignalHandler(); sh.add(this.readyListener, data => { setData(data); setBusy(false); }); sh.add(this.requestListener, req => { setBusy(true); }); this.requestListener.invoke(request ?? null); return () => { sh.clear(); }; }, dependency ?? []); return [data, busy]; } clear() { this.requestListener.removeAll(); this.readyListener.removeAll(); } } exports.Binder = Binder;