UNPKG

@skyway-sdk/common

Version:

The official Next Generation JavaScript SDK for SkyWay

200 lines 6.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EventDisposer = exports.Events = exports.Event = void 0; const logger_1 = require("./logger"); const log = new logger_1.Logger('packages/common/src/event.ts'); class Event { /**@internal */ constructor(_onSetListener = () => { }) { this._onSetListener = _onSetListener; this._stack = []; this._eventIndex = 0; /**@internal */ this.emit = (arg) => { for (const task of this._stack) { try { task.execute(arg); } catch (error) { log.error('task throws error', error); } } }; /**@internal */ this.removeAllListeners = () => { this._stack = []; }; /**@internal */ this.pipe = (event) => { return this.add((arg) => event.emit(arg)); }; /** * イベントが起きた時に実行する関数を登録する。 * 戻り値として関数の登録を解除する関数が帰ってくる */ this.add = (callback) => { const id = this._eventIndex; this._stack.push({ execute: callback, id }); this._eventIndex++; const removeListener = () => { this._stack = this._stack.filter((item) => item.id !== id && item); }; const disposer = (disposer) => { disposer.push(removeListener); }; this._onSetListener(); return { removeListener, disposer }; }; /**イベントが起きた時に一度だけ実行される関数を登録する */ this.once = (callback) => { const off = this.add((arg) => { off.removeListener(); callback(arg); }); return off; }; /** * イベントが起きた時に Promise が resolve される * @param timeLimit ms */ this.asPromise = (timeLimit, disposer) => new Promise((resolve, reject) => { const off = this.once((arg) => { if (settled) { return; } settled = true; cleanup(); resolve(arg); }); let timeout; let settled = false; let cancel = () => { }; const cleanup = () => { off.removeListener(); if (timeout) { clearTimeout(timeout); timeout = undefined; } disposer === null || disposer === void 0 ? void 0 : disposer.remove(cancel); }; cancel = () => { if (settled) { return; } settled = true; cleanup(); }; if (timeLimit) { timeout = setTimeout(() => { if (settled) { return; } settled = true; cleanup(); reject(new SerializableError(`Event asPromise timeout : ${timeLimit}`)); }, timeLimit); } disposer === null || disposer === void 0 ? void 0 : disposer.push(cancel); }); /** * イベントが起きた時に実行される boolean を返す関数を登録する。 * 登録した関数が true を返した時に Promise が resolve される * */ this.watch = (callback, /**ms */ timeLimit, disposer) => new Promise((resolve, reject) => { const off = this.add((arg) => { const done = callback(arg); if (done) { if (settled) { return; } settled = true; cleanup(); resolve(arg); } }); let timeout; let settled = false; let cancel = () => { }; const cleanup = () => { off.removeListener(); if (timeout) { clearTimeout(timeout); timeout = undefined; } disposer === null || disposer === void 0 ? void 0 : disposer.remove(cancel); }; cancel = () => { if (settled) { return; } settled = true; cleanup(); }; if (timeLimit) { timeout = setTimeout(() => { if (settled) { return; } settled = true; cleanup(); reject(new SerializableError(`Event watch timeout : ${timeLimit}`)); }, timeLimit); } disposer === null || disposer === void 0 ? void 0 : disposer.push(cancel); }); } /**@internal */ get length() { return this._stack.length; } } exports.Event = Event; /**@internal */ class Events { constructor() { this.events = []; } make() { const event = new Event(); this.events.push(event); return event; } dispose() { this.events.forEach((event) => { event.removeAllListeners(); }); this.events = []; } } exports.Events = Events; /**@internal */ class EventDisposer { constructor() { this._disposer = []; } push(disposer) { this._disposer.push(disposer); } remove(disposer) { this._disposer = this._disposer.filter((item) => item !== disposer); } dispose() { this._disposer.forEach((d) => { d(); }); this._disposer = []; } } exports.EventDisposer = EventDisposer; class SerializableError extends Error { toJSON() { return { name: this.name, message: this.message, stack: this.stack, }; } } //# sourceMappingURL=event.js.map