UNPKG

ember-lifeline

Version:

Ember.js addon for lifecycle aware async tasks and DOM events.

78 lines (70 loc) 2.37 kB
import { assert } from '@ember/debug'; import { throttle } from '@ember/runloop'; import { EmberRunTimer } from '@ember/runloop/types'; import { isDestroying } from '@ember/destroyable'; import { NULL_TIMER_ID, getTimers } from './cancel-task'; import { Destroyable, Timer } from './types'; /** * Runs the function with the provided name immediately, and only once in the time window * specified by the spacing argument. * * Example: * * ```js * import Component from '@glimmer/component'; * import { throttleTask } from 'ember-lifeline'; * * export default LoggerComponent extends Component { * logMe() { * console.log('This will run once immediately, then only once every 300ms.'); * }, * * click() { * throttleTask(this, 'logMe', 300); * }, * }); * ``` * * @function throttleTask * @param { Destroyable } destroyable the instance to register the task for * @param { String } taskName the name of the task to throttle * @param { ...* } [throttleArgs] arguments to pass to the throttled method * @param { Number } spacing the time in the future to run the task * @param { Boolean } [immediate] Trigger the function on the leading instead of the trailing edge of the wait interval. Defaults to true. * @public */ export function throttleTask( destroyable: Destroyable, taskName: any, ...throttleArgs: any[] ): Timer { assert( `Called \`throttleTask\` without a string as the first argument on ${destroyable}.`, typeof taskName === 'string' ); assert( `Called \`throttleTask('${taskName}')\` where '${taskName}' is not a function.`, typeof destroyable[taskName] === 'function' ); if (isDestroying(destroyable)) { return NULL_TIMER_ID; } const lastArgument = throttleArgs[throttleArgs.length - 1]; const spacing = typeof lastArgument === 'boolean' ? throttleArgs[throttleArgs.length - 2] : lastArgument; assert( `Called \`throttleTask\` with incorrect \`spacing\` argument. Expected Number and received \`${spacing}\``, typeof spacing === 'number' ); let timers: Set<EmberRunTimer> = getTimers(destroyable); let cancelId: EmberRunTimer = throttle( destroyable as any, // @ts-ignore Ignores type mismatch issues with passing rest arguments to throttle. taskName, ...throttleArgs ); timers.add(cancelId); return cancelId; }