Skip to content

Commit

Permalink
Merge pull request #43 from AliMD/feat/signal
Browse files Browse the repository at this point in the history
Improve signal
  • Loading branch information
alimd authored Mar 4, 2022
2 parents 45d4922 + 80c2b27 commit 436e87a
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 22 deletions.
53 changes: 41 additions & 12 deletions package/signal/src/signal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import {log, _getSignalObject, _callListeners, _removeSignalListener} from './core';
import type {ListenerOptions, DispatchOptions, ListenerCallback, ListenerObject} from './type';

import {log,
_getSignalObject,
_callListeners,
_removeSignalListener,
} from './core';

import type {
ListenerOptions,
DispatchOptions,
ListenerCallback,
ListenerObject,
SignalProvider,
SignalProviderOptions,
} from './type';

/**
* Add new listener to specific signal.
Expand All @@ -11,13 +22,13 @@ import type {ListenerOptions, DispatchOptions, ListenerCallback, ListenerObject}
export function addSignalListener<SignalName extends keyof VatrSignals>(
signalName: SignalName,
signalCallback: ListenerCallback<SignalName>,
options?: Partial<ListenerOptions>,
options?: ListenerOptions,
): symbol {
log('addSignalListener(%s, %o)', signalName, options);

const signal = _getSignalObject(signalName);
const listener: ListenerObject<SignalName> = {
id: Symbol('Vatr Signal Listener'),
id: Symbol('Vatr signal listener for ' + signalName),
once: options?.once ?? false,
disabled: options?.disabled ?? false,
callback: signalCallback,
Expand Down Expand Up @@ -80,8 +91,8 @@ export function removeSignalListener<SignalName extends keyof VatrSignals>(
*/
export function dispatchSignal<SignalName extends keyof VatrSignals>(
signalName: SignalName,
value?: VatrSignals[SignalName],
options?: Partial<DispatchOptions>,
value: VatrSignals[SignalName],
options?: DispatchOptions,
): void {
log('dispatchSignal(%s, %o, %o)', signalName, value, options);

Expand Down Expand Up @@ -139,18 +150,36 @@ export function requestSignal<SignalName extends keyof VatrRequestSignals>(
* }
* }
*/
export function addSignalProvider<SignalName extends keyof VatrRequestSignals>(
export function setSignalProvider<SignalName extends keyof VatrRequestSignals>(
signalName: SignalName,
signalCallback: (detail: VatrRequestSignals[SignalName]) => void | Promise<void>,
signalProvider: SignalProvider<SignalName>,
options?: SignalProviderOptions,
): symbol {
log('addSignalProvider(%s)', signalName);
log('setSignalProvider(%s)', signalName);
// @TODO: refactor with removeSignalProvider
const signal = _getSignalObject(`request-${signalName}` as unknown as SignalName);
if (signal.listenerList.length>0) {
log('setSignalProvider(%s): WARNING! another provider defined and will removed!',
signalName, signal.listenerList.length);
signal.listenerList = [];
}

const _callback = async (requestParam: VatrRequestSignals[SignalName]) => {
const signalValue = await signalProvider(requestParam);
if (signalValue !== undefined) { // null can be a valid value.
dispatchSignal(signalName, signalValue, {debounce: options?.debounce ?? true});
}
};

return addSignalListener(
`request-${signalName}` as unknown as SignalName,
signalCallback as unknown as ListenerCallback<SignalName>,
{receivePrevious: true},
_callback as unknown as ListenerCallback<SignalName>,
{receivePrevious: options?.receivePrevious ?? true},
);
}

// @TODO: removeSignalProvider(signalName): void

/**
* Resolved with signal value when signal is ready base on requested options.
* By default, wait new signal received.
Expand Down
44 changes: 34 additions & 10 deletions package/signal/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,56 +17,80 @@ declare global {
/**
* addSignalListener options type
*/
export interface ListenerOptions
{
export interface ListenerOptions {
/**
* If true, the listener will be called only once.
* @default false
*/
once: boolean;
once?: boolean;

/**
* If true, the listener will be called before other.
* @default false
*/
priority: boolean;
priority?: boolean;

/**
* If true, the listener will be defined disabled by default.
*
* @default false
*/
disabled: boolean;
disabled?: boolean;

/**
* Calling this listener (callback) with preview signal value (if dispatched before).
* If Immediate, the listener will be called immediately without any debounce for preview signal.
*
* @default true
*/
receivePrevious: boolean | 'Immediate';
receivePrevious?: boolean | 'Immediate';
}

/**
* dispatchSignal options type
*/
export interface DispatchOptions
{
export interface DispatchOptions {
/**
* If true, the dispatch will be send after animation frame debounce.
* If false, every signal is matter and count.
* tips: debounce work like throttle this means listeners call with last dispatch value.
*
* @default true
*/
debounce?: boolean;
}

export interface SignalProviderOptions {
/**
* Calling signal provider (request signal callback) with preview signal value (if dispatched before).
* If Immediate, the listener will be called immediately without any debounce for preview signal.
*
* @default true
*/
receivePrevious?: boolean | 'Immediate';

/**
* If true, the dispatch will be send after animation frame debounce.
* If false, every signal is matter and count.
* tips: debounce work like throttle this means listeners call with last dispatch value.
*
* @default true
*/
debounce: boolean;
debounce?: boolean;
}

/**
* Signal listeners callback function type.
*/
export type ListenerCallback<SignalName extends keyof VatrSignals> =
(detail: VatrSignals[SignalName]) => void | Promise<void>;
(signalValue: VatrSignals[SignalName]) => void | Promise<void>;

/**
* Signal provider function type used to setSignalProvider.
*/
export type SignalProvider<SignalName extends keyof VatrRequestSignals> =
(requestParam: VatrRequestSignals[SignalName]) =>
VatrSignals[SignalName] | Promise<VatrSignals[SignalName]> | void | Promise<void>

/**
* Signal listeners object in database.
Expand Down

0 comments on commit 436e87a

Please sign in to comment.