Back to All Snippets

Utilities

Helpful utilities and tools

10 snippets found

Generate UUID

Create unique identifiers

Generates RFC4122 version 4 compliant UUIDs (Universally Unique Identifiers). Uses crypto.randomUUID() when available (modern browsers) with a fallback implementation for older environments. Essential for creating unique keys, session IDs, or any scenario requiring guaranteed unique identifiers.

javascriptiduuid
function generateUUID(): string {
  // Modern browsers support crypto.randomUUID()
  if (typeof crypto !== 'undefined' && crypto.randomUUID) {
    return crypto.randomUUID();
  }

  // Fallback for older browsers
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

// Usage
const id = generateUUID();
console.log(id); // "550e8400-e29b-41d4-a716-446655440000"

Sleep Function

Async delay utility

A Promise-based sleep function that pauses async execution for a specified duration. Much cleaner than setTimeout in async contexts and enables readable sequential code with await. Perfect for rate limiting API calls, creating animations, or adding delays in async workflows.

javascriptasyncdelay
function sleep(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// Usage
async function example() {
  console.log('Starting...');
  await sleep(2000); // Wait 2 seconds
  console.log('Done!');
}

// Rate limiting API calls
async function fetchWithDelay(urls: string[]) {
  for (const url of urls) {
    const response = await fetch(url);
    const data = await response.json();
    console.log(data);
    await sleep(1000); // Wait 1 second between requests
  }
}

Retry Function

Retry failed async operations

Automatically retries a failed async operation with configurable attempts and delay. Essential for handling unreliable network requests, external API calls, or any operation that might temporarily fail. Includes exponential backoff support for production use.

javascriptasyncerror-handling
async function retry<T>(
  fn: () => Promise<T>,
  options: {
    attempts?: number;
    delay?: number;
    exponentialBackoff?: boolean;
  } = {}
): Promise<T> {
  const { attempts = 3, delay = 1000, exponentialBackoff = false } = options;

  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (error) {
      const isLastAttempt = i === attempts - 1;
      if (isLastAttempt) throw error;

      const waitTime = exponentialBackoff ? delay * Math.pow(2, i) : delay;
      await new Promise(resolve => setTimeout(resolve, waitTime));
    }
  }

  throw new Error('All retry attempts failed');
}

// Usage
async function fetchData() {
  return retry(
    () => fetch('https://api.example.com/data').then(r => r.json()),
    { attempts: 3, delay: 1000, exponentialBackoff: true }
  );
}

Random Number in Range

Generate random number between min and max

Generates a random number within a specified range, with options for integers or decimals. More convenient than using Math.random() directly and handles the min/max calculation. Useful for games, random selection, testing with random data, or lottery systems.

javascriptrandommath
function randomRange(min: number, max: number, integer: boolean = false): number {
  const random = Math.random() * (max - min) + min;
  return integer ? Math.floor(random) : random;
}

// Usage
randomRange(1, 10);          // 7.384729384 (decimal)
randomRange(1, 10, true);    // 7 (integer)
randomRange(0, 1);           // 0.573821 (percentage)

// Random array element
function randomElement<T>(array: T[]): T {
  return array[randomRange(0, array.length, true)];
}

const colors = ['red', 'blue', 'green'];
console.log(randomElement(colors)); // 'blue'

Memoize Function

Cache function results for performance

Caches function results based on arguments to avoid expensive recalculations. Uses a Map for O(1) lookups with support for custom cache key generation. Essential for expensive computations, recursive functions, or repeated API calls with the same parameters.

javascriptperformancecache
function memoize<T extends (...args: any[]) => any>(
  fn: T,
  getKey?: (...args: Parameters<T>) => string
): T & { cache: Map<string, ReturnType<T>>; clear: () => void } {
  const cache = new Map<string, ReturnType<T>>();

  const defaultGetKey = (...args: Parameters<T>) => JSON.stringify(args);
  const keyFn = getKey || defaultGetKey;

  const memoized = function (...args: Parameters<T>): ReturnType<T> {
    const key = keyFn(...args);

    if (cache.has(key)) {
      return cache.get(key)!;
    }

    const result = fn(...args);
    cache.set(key, result);
    return result;
  } as T & { cache: Map<string, ReturnType<T>>; clear: () => void };

  memoized.cache = cache;
  memoized.clear = () => cache.clear();

  return memoized;
}

// Usage
const fibonacci = memoize((n: number): number => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

console.log(fibonacci(40)); // Fast with memoization
console.log(fibonacci.cache.size); // Shows cached values

// Custom cache key
const fetchUser = memoize(
  async (id: number) => fetch(`/api/users/${id}`).then(r => r.json()),
  (id) => `user-${id}`
);

Group Array by Property

Group array elements by a key

Groups array elements into an object based on a specified key or function result. Essential for categorizing data, creating indexes, or organizing collections. Returns an object where keys are the group identifiers and values are arrays of matching items.

javascriptarrayobject
function groupBy<T, K extends string | number>(
  array: T[],
  key: keyof T | ((item: T) => K)
): Record<K, T[]> {
  return array.reduce((result, item) => {
    const groupKey = typeof key === 'function' ? key(item) : String(item[key]) as K;
    if (!result[groupKey]) {
      result[groupKey] = [];
    }
    result[groupKey].push(item);
    return result;
  }, {} as Record<K, T[]>);
}

// Usage
interface User {
  name: string;
  role: string;
  age: number;
}

const users: User[] = [
  { name: 'Alice', role: 'admin', age: 30 },
  { name: 'Bob', role: 'user', age: 25 },
  { name: 'Charlie', role: 'admin', age: 35 },
];

// Group by property
const byRole = groupBy(users, 'role');
// { admin: [Alice, Charlie], user: [Bob] }

// Group by function
const byAgeGroup = groupBy(users, (user) => user.age >= 30 ? 'senior' : 'junior');
// { senior: [Alice, Charlie], junior: [Bob] }

Deep Clone Object

Create a deep copy of objects

Creates a deep copy of objects, arrays, dates, and primitives using the structured clone algorithm when available. Preserves nested structures and handles circular references. Essential for immutable updates, state management, or avoiding reference issues.

javascriptobjectclone
function deepClone<T>(obj: T): T {
  // Use native structuredClone if available (modern browsers)
  if (typeof structuredClone === 'function') {
    return structuredClone(obj);
  }

  // Fallback for older environments
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  if (obj instanceof Date) {
    return new Date(obj.getTime()) as T;
  }

  if (obj instanceof Array) {
    return obj.map(item => deepClone(item)) as T;
  }

  if (obj instanceof Object) {
    const clonedObj = {} as T;
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        clonedObj[key] = deepClone(obj[key]);
      }
    }
    return clonedObj;
  }

  return obj;
}

// Usage
const original = {
  name: 'John',
  address: {
    city: 'New York',
    zip: '10001'
  },
  hobbies: ['reading', 'coding']
};

const copy = deepClone(original);
copy.address.city = 'Boston';

console.log(original.address.city); // 'New York' (unchanged)
console.log(copy.address.city);     // 'Boston'

Advanced Debounce

Debounce with leading/trailing options

An advanced debounce implementation with leading and trailing edge options. Leading edge executes immediately on first call, trailing edge executes after the delay. Includes a cancel method to abort pending executions. Perfect for search inputs, resize handlers, or any high-frequency event.

javascriptperformancedebounce
function debounce<T extends (...args: any[]) => any>(
  func: T,
  wait: number,
  options: { leading?: boolean; trailing?: boolean } = {}
): T & { cancel: () => void } {
  const { leading = false, trailing = true } = options;
  let timeout: NodeJS.Timeout | null = null;
  let result: any;

  const debounced = function (this: any, ...args: Parameters<T>) {
    const callNow = leading && !timeout;

    const later = () => {
      timeout = null;
      if (trailing) {
        result = func.apply(this, args);
      }
    };

    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(later, wait);

    if (callNow) {
      result = func.apply(this, args);
    }

    return result;
  } as T & { cancel: () => void };

  debounced.cancel = () => {
    if (timeout) {
      clearTimeout(timeout);
      timeout = null;
    }
  };

  return debounced;
}

// Usage
const search = debounce(
  (query: string) => console.log('Searching:', query),
  500,
  { leading: false, trailing: true }
);

search('hello');
search('hello world');
// Only logs 'Searching: hello world' after 500ms

// Cancel pending execution
search.cancel();

Clamp Number

Restrict a number to a range

Constrains a number to stay within a specified min and max range. Returns the number if it's within range, otherwise returns the nearest boundary. Essential for volume controls, progress bars, pagination, or any scenario where values must stay within bounds.

javascriptmathnumber
function clamp(value: number, min: number, max: number): number {
  return Math.min(Math.max(value, min), max);
}

// Usage
clamp(5, 0, 10);   // 5 (within range)
clamp(-5, 0, 10);  // 0 (clamped to min)
clamp(15, 0, 10);  // 10 (clamped to max)

// Practical example: Volume control
function setVolume(volume: number) {
  const clampedVolume = clamp(volume, 0, 100);
  audio.volume = clampedVolume / 100;
}

Chunk Array

Split array into smaller chunks

Divides an array into smaller arrays of a specified size. Useful for pagination, batch processing, creating grid layouts, or processing large datasets in manageable chunks. The last chunk may be smaller if the array doesn't divide evenly.

javascriptarrayutility
function chunk<T>(array: T[], size: number): T[][] {
  const chunks: T[][] = [];
  for (let i = 0; i < array.length; i += size) {
    chunks.push(array.slice(i, i + size));
  }
  return chunks;
}

// Usage
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(chunk(numbers, 3));
// [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

// Pagination
function paginate<T>(items: T[], page: number, perPage: number): T[] {
  const chunks = chunk(items, perPage);
  return chunks[page - 1] || [];
}