@skyway-sdk/common
Version:
The official Next Generation JavaScript SDK for SkyWay
200 lines • 6.29 kB
JavaScript
;
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