Skip to content

Commit

Permalink
feat(signal): improve signal provider by dispatch return content
Browse files Browse the repository at this point in the history
  • Loading branch information
alimd committed Mar 4, 2022
1 parent 6e09f87 commit 80c2b27
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 18 deletions.
39 changes: 30 additions & 9 deletions package/signal/src/signal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +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 @@ -10,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 @@ -79,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 @@ -140,7 +152,8 @@ export function requestSignal<SignalName extends keyof VatrRequestSignals>(
*/
export function setSignalProvider<SignalName extends keyof VatrRequestSignals>(
signalName: SignalName,
signalCallback: (requestParam: VatrRequestSignals[SignalName]) => void | Promise<void>,
signalProvider: SignalProvider<SignalName>,
options?: SignalProviderOptions,
): symbol {
log('setSignalProvider(%s)', signalName);
// @TODO: refactor with removeSignalProvider
Expand All @@ -150,10 +163,18 @@ export function setSignalProvider<SignalName extends keyof VatrRequestSignals>(
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},
);
}

Expand Down
42 changes: 33 additions & 9 deletions package/signal/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,66 @@ 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;
}

/**
Expand All @@ -68,6 +85,13 @@ export interface DispatchOptions
export type ListenerCallback<SignalName extends keyof VatrSignals> =
(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 80c2b27

Please sign in to comment.