CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-hapi--hoek

General purpose node utilities providing object manipulation, array operations, string utilities, data validation, async utilities, and path operations for the hapi ecosystem.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

async-promise-utilities.mddocs/

Async and Promise Utilities

Promise-based utilities for timing control, blocking, and promise detection in async workflows with support for various timeout scenarios and promise identification.

Capabilities

Wait

Returns a Promise that resolves after the requested timeout with optional return value and custom setTimeout support.

/**
 * Returns a Promise that resolves after the requested timeout
 * @param timeout - The number of milliseconds to wait before resolving the Promise
 * @param returnValue - The value that the Promise will resolve to
 * @param options - Optional settings with custom setTimeout implementation
 * @returns A Promise that resolves with returnValue after the specified timeout
 */
function wait<T>(timeout?: number, returnValue?: T, options?: wait.Options): Promise<T>;

namespace wait {
  interface Options {
    /** Custom setTimeout function to use instead of global setTimeout */
    readonly setTimeout?: (callback: () => void, delay: number) => any;
  }
}

Usage Examples:

import { wait } from "@hapi/hoek";

// Basic delay
await wait(1000); // Wait for 1 second
console.log('1 second has passed');

// Wait with return value
const result = await wait(2000, 'completed');
console.log(result); // 'completed' after 2 seconds

// Use in async workflows
async function processWithDelay() {
  console.log('Starting process...');
  await wait(500);
  console.log('Step 1 complete');
  await wait(1000);
  console.log('Step 2 complete');
  return 'Process finished';
}

// Timeout for rate limiting
async function rateLimitedAPI() {
  const results = [];
  for (let i = 0; i < 5; i++) {
    const data = await fetchData(i);
    results.push(data);
    await wait(200); // 200ms between requests
  }
  return results;
}

// Retry with exponential backoff
async function retryWithBackoff(operation: () => Promise<any>, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
      console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
      await wait(delay);
    }
  }
}

// Simulating slow operations for testing
async function simulateSlowAPI() {
  await wait(Math.random() * 1000, 'API response');
  return { data: 'response data' };
}

// Timeout with specific return values
const timeoutResult = await wait(5000, { status: 'timeout', code: 408 });

// BigInt timeout handling
const bigIntTimeout = 1000n;
await wait(bigIntTimeout); // Automatically converted to number

// Infinite timeout (never resolves)
const neverResolving = wait(Infinity); // Promise that never resolves

// Very large timeout handling
const largeTimeout = Number.MAX_SAFE_INTEGER;
await wait(largeTimeout); // Handled safely with internal chunking

// Custom setTimeout function (for testing or special environments)
const customWait = (timeout: number, returnValue: any, options: any) => {
  return wait(timeout, returnValue, {
    setTimeout: (callback: Function, delay: number) => {
      // Custom timeout implementation
      return global.setTimeout(callback, delay);
    }
  });
};

Block

Returns a Promise that never resolves, useful for creating permanent blocking conditions.

/**
 * Returns a Promise that never resolves
 * @returns A Promise that never resolves (blocks forever)
 */
function block(): Promise<void>;

Usage Examples:

import { block } from "@hapi/hoek";

// Create a permanent block
async function waitForever() {
  console.log('Starting infinite wait...');
  await block(); // This never resolves
  console.log('This line never executes');
}

// Use in conditional blocking
async function conditionalBlock(shouldBlock: boolean) {
  if (shouldBlock) {
    await block(); // Permanently blocks execution
  }
  return 'execution continued';
}

// Server shutdown prevention
async function keepServerAlive() {
  console.log('Server is running...');
  await block(); // Keeps the process alive indefinitely
}

// Testing timeout behaviors
async function testTimeout() {
  const timeoutPromise = new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error('Timeout')), 5000);
  });
  
  try {
    await Promise.race([block(), timeoutPromise]);
  } catch (error) {
    console.log('Timeout occurred as expected');
  }
}

// Creating permanent background tasks
async function backgroundWorker() {
  setInterval(() => {
    console.log('Background task running...');
  }, 1000);
  
  await block(); // Keep the worker alive forever
}

// Process lifecycle management
async function gracefulShutdown() {
  process.on('SIGTERM', () => {
    console.log('Received SIGTERM, shutting down...');
    process.exit(0);
  });
  
  console.log('Application started');
  await block(); // Keep process alive until signal received
}

// Development server that never stops
async function devServer() {
  console.log('Development server starting on port 3000...');
  // Start server logic here
  await block(); // Keep server running indefinitely
}

Is Promise

Determines if an object is a promise by checking for thenable interface.

/**
 * Determines if an object is a promise
 * @param promise - The object being tested
 * @returns true if the object is a promise, otherwise false
 */
function isPromise(promise: any): boolean;

Usage Examples:

import { isPromise } from "@hapi/hoek";

// Basic promise detection
const regularPromise = Promise.resolve('value');
const notPromise = 'string';

console.log(isPromise(regularPromise)); // true
console.log(isPromise(notPromise));     // false

// Async function detection
async function asyncFunction() {
  return 'async result';
}

const asyncResult = asyncFunction(); // This is a Promise
console.log(isPromise(asyncResult)); // true

// Thenable object detection
const thenable = {
  then: (resolve: Function, reject: Function) => {
    resolve('thenable result');
  }
};

console.log(isPromise(thenable)); // true

// Function that handles both sync and async values
function processValue(value: any) {
  if (isPromise(value)) {
    return value.then((result: any) => {
      console.log('Async result:', result);
      return result;
    });
  } else {
    console.log('Sync result:', value);
    return value;
  }
}

// Usage with various value types
processValue('immediate value');
processValue(Promise.resolve('promise value'));
processValue(asyncFunction());

// Conditional awaiting
async function conditionalAwait(maybePromise: any) {
  if (isPromise(maybePromise)) {
    const result = await maybePromise;
    return `Awaited: ${result}`;
  } else {
    return `Immediate: ${maybePromise}`;
  }
}

// API response handling
function handleAPIResponse(response: any) {
  if (isPromise(response)) {
    // Handle async API response
    return response.then(data => ({ async: true, data }));
  } else {
    // Handle sync/cached response
    return { async: false, data: response };
  }
}

// Utility for mixed return types
class DataProcessor {
  process(input: any): any {
    const result = this.processSync(input);
    
    if (isPromise(result)) {
      return result.then(data => this.postProcess(data));
    } else {
      return this.postProcess(result);
    }
  }
  
  private processSync(input: any): any {
    // May return sync value or Promise based on input
    if (input.needsAsync) {
      return fetch('/api/data').then(r => r.json());
    }
    return { processed: input };
  }
  
  private postProcess(data: any) {
    return { ...data, timestamp: Date.now() };
  }
}

// Testing utilities
function createMockResponse(shouldBeAsync: boolean) {
  if (shouldBeAsync) {
    return Promise.resolve({ mocked: true });
  }
  return { mocked: true };
}

// Type checking with validation
function validatePromise(value: any): Promise<any> {
  if (!isPromise(value)) {
    throw new Error('Expected a Promise');
  }
  return value;
}

// Error handling for mixed types
async function safeDifficultProcess(value: any) {
  try {
    if (isPromise(value)) {
      return await value;
    }
    return value;
  } catch (error) {
    console.error('Error processing value:', error);
    return null;
  }
}

Important Notes:

  • wait handles various edge cases including BigInt timeouts, infinite timeouts, and very large timeout values
  • Internal timer chunking in wait prevents JavaScript timer limitations for very long timeouts
  • block is useful for keeping processes alive or creating permanent blocking conditions in specific scenarios
  • isPromise checks for thenable interface (objects with then method) rather than just Promise instances
  • All utilities work seamlessly with async/await syntax and Promise-based workflows
  • Perfect for building robust async applications with proper timing control and promise handling

docs

array-operations.md

async-promise-utilities.md

data-utilities.md

function-utilities.md

index.md

object-operations.md

path-operations.md

performance-benchmarking.md

string-utilities.md

validation-assertions.md

tile.json