UNPKG

react-sub-unsub

Version:
268 lines (267 loc) 12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Subs = exports.Subscribe = void 0; /** * Static functions for subscribing and unsubscribing to and from events. */ class Subscribe { /** * Call a function that adds a listener and returns a function that will unsubscribe the listener. * * The function passed in will be called immediately to add the listener, * and its Unsubscribe function will be returned. * * @param subscribe The subscribe function, which returns an Unsubscribe. Will be called immediately. * @returns The Unsubscribe function for this subscription. */ static subscribe(subscribe) { try { return subscribe(); } catch (e) { console.error(e); } return () => { // No-op when catching an error }; } /** * Subscribe to an emitter event. Returns a function that will unsubscribe the listener. * * @param eventEmitter The [EventEmitter](https://nodejs.org/api/events.html#class-eventemitter) to subscribe to. * @param eventName The name of the event to listen for. * @param listener The listener callback that is called when the event occurs. * @returns The Unsubscribe function for this subscription. */ static subscribeEvent(eventEmitter, eventName, listener) { eventEmitter.addListener(eventName, listener); return () => { eventEmitter.removeListener(eventName, listener); }; } /** * Appends an event listener for events whose type attribute value is type. The callback argument sets the callback * that will be invoked when the event is dispatched. * * The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the * method behaves exactly as if the value was specified as options's capture. * * When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute * value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute * value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. * * Returns a function that will unsubscribe the listener. * * @param domObj The DOM object to subscribe to for events. * @param eventName The name of the event to listen for. * @param listener The listener callback that is called when the event occurs. * @param options Listener-specific options. See function description. * @returns The Unsubscribe function for this subscription. */ static subscribeDOMEvent(domObj, eventName, listener, options) { domObj.addEventListener(eventName, listener, options); return () => { domObj.removeEventListener(eventName, listener, options); }; } /** * Sets a timer which executes a function once the timer expires using `setTimeout`. * Returns an unsubscribe function that clears the timeout using `clearTimeout`. * * @param handler A function to be executed after the timer expires. * @param delay The time, in milliseconds that the timer should wait before the specified function or code is executed. If this parameter is omitted, a value of 0 is used, meaning execute "immediately", or more accurately, the next event cycle. * @param args Additional arguments which are passed through to the handler specified. * @returns The Unsubscribe function for this subscription. */ static setTimeout(handler, delay, ...args) { const timeout = setTimeout(handler, delay, args); return () => clearTimeout(timeout); } /** * Repeatedly calls a function with a fixed time delay between each call using `setInterval`. * Returns an unsubscribe function that clears the interval using `clearInterval`. * * @param handler A function to be executed after the timer expires. * @param delay The time, in milliseconds (thousandths of a second), the timer should delay in between executions of the specified function or code. Defaults to 0 if not specified. * @param args Additional arguments which are passed through to the handler once the timer expires. * @returns The Unsubscribe function for this subscription. */ static setInterval(handler, delay, ...args) { const interval = setInterval(handler, delay, args); return () => clearInterval(interval); } /** * Call all unsubscribe functions passed in. Can pass either an array of unsubscribe functions, * or a single unsubscribe function. * * @param unsubs An array of unsubscribe functions, or a single unsubscribe function. */ static unsubAll(unsubs) { if (Array.isArray(unsubs)) { unsubs.forEach((unsub) => { try { unsub(); } catch (e) { console.error(e); } }); } else { try { unsubs(); } catch (e) { console.error(e); } } } /** * Creates and returns a cleanup function that, when called, calls all unsubscribe functions provided. * * @param unsubs All subscriptions to be unsubscribed when the returned cleanup function is called. * @returns A cleanup function that unsubscribes all subscriptions provided. */ static createCleanup(unsubs) { return () => Subscribe.unsubAll(unsubs); } } exports.Subscribe = Subscribe; /** * A Subs object can be used to subscribe and unsubscribe to events, * and to collect subscriptions in an array to be unsubscribed all at once. * * Calling any of the subscribe functions will add the unsubscribe function to * an internal array. You can then call `unsubAll()` to unsubscribe all * at once and clear the list. */ class Subs { /** * Construct a new Subs object. * * A Subs object can be used to subscribe and unsubscribe to events, * and to collect subscriptions in an array to be unsubscribed all at once. * * Calling any of the subscribe functions will add the unsubscribe function to * an internal array. You can then call `unsubAll()` to unsubscribe all * at once and clear the list. * * You can optionally pass in an array of unsubscribe functions to start with. * * @param list Optional array of unsubscribe functions. Defaults to an empty list. */ constructor( /** A list of unsubscribe functions for all subscribe calls that have been made. */ list = []) { this.list = list; } /** * Call a function that adds a listener and returns a function that will unsubscribe the listener. * * The function passed in will be called immediately to add the listener, * and its Unsubscribe function will be returned. * * The Unsubscribe function will be added to the internal list of unsubs. You can unsubscribe all by calling `unsubAll()`. * * @param subscribe The subscribe function, which returns an Unsubscribe. Will be called immediately. * @returns The Unsubscribe function for this subscription. */ subscribe(subscribe) { const unsub = Subscribe.subscribe(subscribe); this.push(unsub); return unsub; } /** * Subscribe to an emitter event. Returns a function that will unsubscribe the listener. * * The Unsubscribe function will be added to the internal list of unsubs. You can unsubscribe all by calling `unsubAll()`. * * @param eventEmitter The [EventEmitter](https://nodejs.org/api/events.html#class-eventemitter) to subscribe to. * @param eventName The name of the event to listen for. * @param listener The listener callback that is called when the event occurs. * @returns The Unsubscribe function for this subscription. */ subscribeEvent(eventEmitter, eventName, listener) { const unsub = Subscribe.subscribeEvent(eventEmitter, eventName, listener); this.push(unsub); return unsub; } /** * Subscribe to an event on a DOM object (Window or Node). Returns a function that will unsubscribe the listener. * * The Unsubscribe function will be added to the internal list of unsubs. You can unsubscribe all by calling `unsubAll()`. * * @param domObj The DOM object to subscribe to for events. * @param eventName The name of the event to listen for. * @param listener The listener callback that is called when the event occurs. * @returns The Unsubscribe function for this subscription. */ subscribeDOMEvent(domObj, eventName, listener) { const unsub = Subscribe.subscribeDOMEvent(domObj, eventName, listener); this.push(unsub); return unsub; } /** * Sets a timer which executes a function once the timer expires using `setTimeout`. * Returns an unsubscribe function that clears the timeout using `clearTimeout`. * * The Unsubscribe function will be added to the internal list of unsubs. You can unsubscribe all by calling `unsubAll()`. * * @param handler A function to be executed after the timer expires. * @param delay The time, in milliseconds that the timer should wait before the specified function or code is executed. If this parameter is omitted, a value of 0 is used, meaning execute "immediately", or more accurately, the next event cycle. * @param args Additional arguments which are passed through to the handler specified. * @returns The Unsubscribe function for this subscription. */ setTimeout(handler, delay, ...args) { const timeout = setTimeout(handler, delay, args); const unsub = () => clearTimeout(timeout); this.push(unsub); return unsub; } /** * Repeatedly calls a function with a fixed time delay between each call using `setInterval`. * Returns an unsubscribe function that clears the interval using `clearInterval`. * * The Unsubscribe function will be added to the internal list of unsubs. You can unsubscribe all by calling `unsubAll()`. * * @param handler A function to be executed after the timer expires. * @param delay The time, in milliseconds (thousandths of a second), the timer should delay in between executions of the specified function or code. Defaults to 0 if not specified. * @param args Additional arguments which are passed through to the handler once the timer expires. * @returns The Unsubscribe function for this subscription. */ setInterval(handler, delay, ...args) { const interval = setInterval(handler, delay, args); const unsub = () => clearInterval(interval); this.push(unsub); return unsub; } /** * Pushes an unsubscribe function onto the subscription list. * * You can unsubscribe all by calling `unsubAll()`. * * @param unsub The unsubscribe function to push to the subscription list. */ push(unsub) { this.list.push(unsub); } /** * Call all unsubscribe functions and clear the unsubscribe list. */ unsubAll() { Subscribe.unsubAll(this.list); // Empty the array, maintain the reference this.list.splice(0, this.list.length); } /** * Creates and returns a cleanup function that, when called, calls all unsubscribe functions and clears the unsubscribe list. * * @returns A cleanup function that unsubscribes all subscriptions and clears the unsubscribe list. */ createCleanup() { return () => { this.unsubAll(); }; } } exports.Subs = Subs;