All files / core/src/utils task.ts

100% Statements 36/36
100% Branches 8/8
100% Functions 3/3
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 831x                                                                             1x 47x 47x 47x 47x   47x 182x 182x 105x 105x   182x 182x   182x 105x 103x 103x 103x   103x   103x 103x 103x 103x 1x 1x 103x 105x 105x   182x 182x   47x 1x 1x 1x   47x 47x  
import { captureStack } from '../exception.js';
 
/**
 * Type definition for a task handler function.
 * @template T - The type of context data passed to the handler
 * @param init - The initial context when the task was first scheduled
 * @param current - The most recent context when the task was last scheduled
 * @returns A promise for async operations or void for sync operations
 */
export type TaskHandler<T> = (init: T, current: T) => Promise<void> | void;
 
/**
 * Type definition for a task scheduler function.
 * @template T - The type of context data that can be passed to the handler
 * @param fn - The task handler function to execute
 * @param context - Optional context data to pass to the handler
 */
export type TaskScheduler<T> = (fn: TaskHandler<T>, context?: T) => void;
 
/**
 * Type definition for a task destroyer function.
 * Used to clean up and cancel any pending tasks.
 */
export type TaskDestroyer = () => void;
 
export type MicroTask<T> = [TaskScheduler<T>, TaskDestroyer];
 
/**
 * Creates a microtask scheduler that batches multiple calls into a single execution.
 *
 * This function returns a scheduler and destroyer pair that allows you to schedule
 * tasks which will be executed after a specified timeout. If multiple tasks are
 * scheduled within the timeout period, only the last one will be executed with
 * the initial and last context values.
 *
 * @template T - The type of context data that can be passed to the handler
 * @param timeout - The timeout in milliseconds before executing the task (default: 10ms)
 * @returns A tuple containing the scheduler and destroyer functions
 */
export function microtask<T = undefined>(timeout = 10): MicroTask<T> {
  let initContext: T | undefined = undefined;
  let lastContext: T | undefined = undefined;
  let executor: TaskHandler<T> | undefined = undefined;
  let activeId: number | undefined = undefined;
 
  const schedule = (fn: TaskHandler<T>, context?: T) => {
    if (typeof context !== 'undefined') {
      if (typeof initContext === 'undefined') {
        initContext = context;
      }
 
      lastContext = context;
    }
 
    if (typeof executor !== 'function') {
      activeId = setTimeout(async () => {
        const execFn = executor;
        const initValue = initContext;
        const lastValue = lastContext;
 
        executor = initContext = lastContext = activeId = undefined;
 
        if (typeof execFn === 'function') {
          try {
            await execFn(initValue as T, lastValue as T);
          } catch (error) {
            captureStack.error.external('Scheduler execution failed.', error as Error);
          }
        }
      }, timeout) as never;
    }
 
    executor = fn;
  };
 
  const destroy = () => {
    clearTimeout(activeId);
    executor = initContext = lastContext = activeId = undefined;
  };
 
  return [schedule, destroy];
}