diff --git a/packages/core/signal/src/core.ts b/packages/core/signal/src/core.ts index 34c5e8137..2f4541615 100644 --- a/packages/core/signal/src/core.ts +++ b/packages/core/signal/src/core.ts @@ -18,6 +18,11 @@ alwatrRegisteredList.push({ version: '{{ALWATR_VERSION}}', }); +/** + * Listener `id` + */ +let _lastListenerId = 0; + /** * Signal stack database. */ @@ -69,7 +74,7 @@ function __callListeners(signal: SignalO signal.listenerList .filter((listener) => !listener.disabled && listener.once) - .forEach((listener) => _removeSignalListener(signal.name, listener.id)); + .forEach((listener) => _removeSignalListener(signal, listener.id)); } /** @@ -82,15 +87,14 @@ function __callListeners(signal: SignalO * ``` */ export function _addSignalListener( - signalName: SignalName, + signal: SignalObject, signalCallback: ListenerCallback, options?: ListenerOptions, ): ListenerObject { - logger.logMethodArgs('addSignalListener', {signalName, options}); + logger.logMethodArgs('addSignalListener', {signal, options}); - const signal = __getSignalObject(signalName); const listener: ListenerObject = { - id: Symbol('Alwatr signal listener for ' + signalName), + id: ++_lastListenerId, once: options?.once ?? false, disabled: options?.disabled ?? false, callback: signalCallback, @@ -102,20 +106,22 @@ export function _addSignalListener( if (signal.value !== undefined) { if (options?.receivePrevious === 'Immediate') { logger.incident('addSignalListener', 'call_signal_callback', 'run callback with previous signal value!', { - signalName, + signalName: signal.name, mode: 'Immediate', }); try { signalCallback(signal.value); } catch (err) { - logger.error('addSignalListener', 'call_signal_callback_failed', (err as Error).stack || err, {signalName}); + logger.error('addSignalListener', 'call_signal_callback_failed', (err as Error).stack || err, { + signalName: signal.name, + }); } callbackCalled = true; } else if (options?.receivePrevious === true) { requestAnimationFrame(() => { if (signal.value !== undefined) { logger.incident('addSignalListener', 'call_signal_callback', 'run callback with previous signal value!', { - signalName, + signalName: signal.name, mode: 'Delay', }); signalCallback(signal.value); @@ -148,11 +154,10 @@ export function _addSignalListener( * ``` */ export function _removeSignalListener( - signalName: SignalName, - listenerId: symbol, + signal: SignalObject, + listenerId: number, ): void { - logger.logMethodArgs('_removeSignalListener', signalName); - const signal = __getSignalObject(signalName); + logger.logMethodArgs('_removeSignalListener', {signal, listenerId}); const listenerIndex = signal.listenerList.findIndex((_listener) => _listener.id === listenerId); if (listenerIndex !== -1) { signal.listenerList.splice(listenerIndex, 1); @@ -166,13 +171,12 @@ export function _removeSignalListener( * dispatchSignal('content-change', content); */ export function _dispatchSignal( - signalName: SignalName, + signal: SignalObject, value: AlwatrSignals[SignalName], options?: DispatchOptions, ): void { - logger.logMethodArgs('dispatchSignal', {signalName, value, options}); + logger.logMethodArgs('dispatchSignal', {signal, value, options}); - const signal = __getSignalObject(signalName); // set value before check signal.debounced for act like throttle (call listeners with last dispatch value). signal.value = value; @@ -210,17 +214,15 @@ export function _dispatchSignal( * ``` */ export function _setSignalProvider( - signalName: SignalName, + signal: SignalObject, signalProvider: SignalProvider, options?: SignalProviderOptions, ): ListenerObject { - logger.logMethodArgs('setSignalProvider', {signalName, options}); + logger.logMethodArgs('setSignalProvider', {signal, options}); - // @TODO: refactor with removeSignalProvider - const signal = __getSignalObject(`request-${signalName}` as unknown as SignalName); if (signal.listenerList.length > 0) { logger.accident('setSignalProvider', 'signal_provider_already_set', 'another provider defined and will removed', { - signalName, + signalName: signal.name, }); signal.listenerList = []; } @@ -229,13 +231,11 @@ export function _setSignalProvider, - {receivePrevious: options?.receivePrevious ?? true}, - ); + return _addSignalListener(signal, _callback as unknown as ListenerCallback, { + receivePrevious: options?.receivePrevious ?? true, + }); } diff --git a/packages/core/signal/src/signal.ts b/packages/core/signal/src/signal.ts index 9e624fec1..7373244db 100644 --- a/packages/core/signal/src/signal.ts +++ b/packages/core/signal/src/signal.ts @@ -23,11 +23,13 @@ import type { */ export class SignalInterface { protected _signal; + protected _requestSignal; protected _logger; constructor(signalName: SignalName) { this._logger = createLogger(`signal<${signalName}>`); this._signal = __getSignalObject(signalName); + this._requestSignal = __getSignalObject(`request-${signalName}` as unknown as SignalName); } /** @@ -131,13 +133,11 @@ export class SignalInterface { * }); * ``` */ - setProvider(signalProvider: SignalProvider, options?: SignalProviderOptions): symbol { + setProvider(signalProvider: SignalProvider, options?: SignalProviderOptions): ListenerObject { this._logger.logMethodArgs('setProvider', {options}); - return _setSignalProvider(this.name, signalProvider, options).id; + return _setSignalProvider(this._signal, signalProvider, options); } - // @TODO: removeProvider(signalName): void - /** * Dispatch request signal and wait for answer (wait for new signal dispatched). * @@ -154,8 +154,7 @@ export class SignalInterface { request(requestParam: AlwatrRequestSignals[SignalName]): Promise { this._logger.logMethodArgs('request', {requestParam}); const nextSignalValuePromise = this.getNextSignalValue(); - _dispatchSignal( - `request-${this.name}` as unknown as SignalName, + _dispatchSignal(this._requestSignal, requestParam as unknown as AlwatrSignals[SignalName], // mastmalize to avoid type error ); return nextSignalValuePromise; @@ -217,7 +216,7 @@ export class SignalInterface { */ dispatch(signalValue: AlwatrSignals[SignalName], options?: DispatchOptions): void { this._logger.logMethodArgs('dispatch', {signalValue, options}); - _dispatchSignal(this._signal.name, signalValue, options); + _dispatchSignal(this._signal, signalValue, options); } /** @@ -232,7 +231,7 @@ export class SignalInterface { */ addListener(listener: ListenerCallback, options?: ListenerOptions): ListenerInterface { this._logger.logMethodArgs('addListener', {listener, options}); - const listenerId = _addSignalListener(this._signal.name, listener, options); + const listenerId = _addSignalListener(this._signal, listener, options); return new ListenerInterface(this._signal, listenerId); } } @@ -279,6 +278,6 @@ export class ListenerInterface { */ remove(): void { this._logger.logMethod('remove'); - _removeSignalListener(this._signal.name, this._listener.id); + _removeSignalListener(this._signal, this._listener.id); } } diff --git a/packages/core/signal/src/type.ts b/packages/core/signal/src/type.ts index 81c36e040..3496a8b04 100644 --- a/packages/core/signal/src/type.ts +++ b/packages/core/signal/src/type.ts @@ -98,9 +98,9 @@ export type SignalProvider = ( */ export interface ListenerObject { /** - * Listener symbol id (unique). + * Unique listener id */ - id: symbol; + id: number; /** * If true, the listener will be called only once and removed automatically after first call