signals, in TypeScript, fast and safe
import { MiniSignal } from 'mini-signals';
// Define a mini-signal
// The optional type argument specifies the listener parameter types
const mySignal = new MiniSignal<[string, string]>();
// Add a listener
// The listener parameter types must match the type argument specified in the MiniSignal constructor
// The returned binding can be used to remove the listener later
const binding = mySignal.add((foo: string, bar: string) => {
console.log('signal dispatched');
expect(foo).toBe('foo');
expect(bar).toBe('bar');
});
// Dispatch the signal, passing parameters to the listeners
mySignal.dispatch('foo', 'bar');
// Remove the listener using the binding
mySignal.detach(binding);const myObject = {
foo: 'bar',
updated: new MiniSignal<[]>(),
};
myObject.updated.add(() => {
console.log('signal dispatched');
expect(myObject.foo).toBe('baz');
});
myObject.foo = 'baz';
myObject.updated.dispatch(); // dispatch signalFlavoring (or branding) a signal ensures that only bindings created by that specific signal can be used to detach listeners from it. This prevents accidentally attempting to detach a binding from a different signal; which would result in a runtime error.
import { MiniSignal } from 'mini-signals';
const mySignal = new MiniSignal<[string, string], 'mySignal'>();
const myOtherSignal = new MiniSignal<[string, string], 'myOtherSignal'>();
const binding = mySignal.add((foo: string, bar: string) => {
// ...
});
expect(() => {
// @ts-ignore
myOtherSignal.detach(binding);
}).toThrow(
'MiniSignal#detach(): MiniSignal listener does not belong to this MiniSignal.'
);Listeners can return Promises to indicate asynchronous operations. The dispatchSerial and dispatchParallel methods will wait for these Promises to resolve before completing.
import { MiniSignal } from 'mini-signals';
// Define a mini-signal
// The optional type argument specifies the listener parameter types
const mySignal = new MiniSignal<[string, string]>();
// Add a listener
// The listener parameter types must match the type argument specified in the MiniSignal constructor
// The returned binding can be used to remove the listener later
const binding = mySignal.add(async (foo: string, bar: string) => {
await doSomethingAsync();
console.log('signal dispatched');
expect(foo).toBe('foo');
expect(bar).toBe('bar');
});
// Dispatch the signal, passing parameters to each listener in series
// Wait for all listeners to complete
await mySignal.dispatchSerial('foo', 'bar');
// Dispatch the signal, passing parameters to each listener in parallel
// Wait for all listeners to complete
await mySignal.dispatchParallel('foo', 'bar');
// Remove the listener using the binding
mySignal.detach(binding);