UNPKG

send-and-receive

Version:

Two small helper methods that simplify communication between nodes in different subtrees of the browser DOM.

159 lines (158 loc) 4.87 kB
interface Context { received: number; remaining: number; cancelled: boolean; cancel: () => void; paused: boolean; pause: () => void; resume: () => void; } export declare type Subscription = Readonly<Context>; /** * Dispatches an event of the specified `type` with the * specified `data` (optional). * * @param type The name of the event. * @param data The optional payload of the event. * @example * * send('player:play', { src: 'song.mp3' }); */ export declare function send(type: string, data?: any): boolean; declare type Callback<T> = (data: T) => void; interface ReceiveOptions { readonly limit: number; } /** * Listens on dispatched events of the specified `type` * and, when it receives one, invokes `callback` with the * data passed when sending. * * @param type The name of the event. * @param callback The function to invoke. * @param options The configuration options. * @returns A subscription object. * @example * * const subscription = receive('player:play', (data) => { * doSomethingWith(data); * }); * * @description * * Use the returned subscription object to retrieve some * metadata or to cancel receiving further events: * * @example * * subscription.received //=> How often has the event been received? * subscription.remaining //=> How many remaining events can it receive? * * subscription.cancelled //=> Did we completely opt out of receiving further events? * subscription.cancel() //=> Unlisten from the event and set cancelled status. * * subscription.paused //=> Did we temporarily stop receiving further events? * subscription.pause() //=> Pause listening and set paused status. * subscription.resume() //=> Resume listening and unset paused status. * * @description * * Note that both `subscription.pause()` and `subscription.resume()` * will throw an error if the subscription has been cancelled. * * By default, the number of events it can receive is not limited, which * means `subscription.remaining` will always return *positive infinity*. * * Besides calling `subscription.cancel()` in order to stop listening to * further events, you can also restrict the number of times the event * will be received by supplying the `limit` option: * * @example * * receive('player:play', callback, { limit: 1 }); * * @description * * Here, after the event has been received once, it will be auto-cancelled. * Furthermore, the subscription's `received` property will have changed * from `0` to `1`, and the `remaining` property from `1` to `0`. */ export declare function receive<T>(type: string, callback: Callback<T>, { limit }?: ReceiveOptions): Subscription; /** * A convenience method for the case when you want to receive * the event only once. * * @param type The name of the event. * @param callback The function to invoke. * @returns A subscription object. * @example * * receiveOnce('player:play', callback); * * @description * * This is semantically the same as calling `receive` with * `{ limit: 1 }` as options. */ export declare function receiveOnce<T>(type: string, callback: Callback<T>): Subscription; declare type CreateResult<T, A extends any[] = [T]> = readonly [(...args: A) => ReturnType<typeof send>, (callback: Callback<T>, options?: ReceiveOptions) => ReturnType<typeof receive>]; /** * A convenience method to create both a sender function and * a receiver function for the specified `type`. * * @param type The name of the event. * @returns An array of size 2, where the first element is the * send function and the second element the receive function. * * @description * * This method is especially useful when coding in TypeScript, * as it allows strict-typing the `data`: * * @example * * // a.ts * import { create } from 'send-and-receive'; * * const [sendPlay, receivePlay] = create<Song>('player:play'); * * export { receivePlay }; * * // later on (button click, etc.) * sendPlay({ src: 'song.mp3' }); * * // b.ts * import { receivePlay } from './a.js'; * * receivePlay((song) => { * doSomethingWith(song.src); * }); * * @description * * Optionally, you can pass a function as the second argument which * transforms the arguments passed to `send` into the data structure * supplied to the `receive` callback: * * @example * * interface Options { * action: "push" | "replace"; * } * * const [navigateTo, receiveNavigateTo] = create( * "navigate-to", * (url: string, options: Options = { action: "push" }) => ({ * ...options, * url, * }) * ); * * // send... * navigateTo("/foo", { action: "replace" }); * * // receive... * receiveNavigateTo(({ url, action }) => history[action](url)); */ export declare function create<T, A extends any[] = [T]>(type: string, buildData?: (...args: A) => T): CreateResult<T, A>; export {};