import type { Fn } from '../../@aileron/declare/index.js'; /** * Schedules a function to execute on the next event loop tick with platform-optimized timing. * * Defers execution to the next iteration of the event loop, ensuring the task runs after * current I/O events and microtasks but before subsequent I/O polling. Automatically * selects the most appropriate scheduling mechanism for the runtime environment, providing * optimal performance for server-side applications and consistent behavior across platforms. * * @param task - Function to execute on the next event loop tick * * @example * Basic next tick scheduling: * ```typescript * import { scheduleNextTick } from '@winglet/common-utils'; * * console.log('1: Synchronous code'); * * // Schedule for next tick (after microtasks and current I/O) * scheduleNextTick(() => { * console.log('5: Next tick executed'); * }); * * // Microtask (executes before next tick) * queueMicrotask(() => { * console.log('3: Microtask executed'); * }); * * // Promise (also microtask) * Promise.resolve().then(() => { * console.log('4: Promise resolved'); * }); * * console.log('2: More synchronous code'); * * // Output order: * // 1: Synchronous code * // 2: More synchronous code * // 3: Microtask executed * // 4: Promise resolved * // 5: Next tick executed * ``` * * @example * I/O coordination in Node.js: * ```typescript * // Server-side I/O coordination * const fs = require('fs'); * * function readFileWithNextTick(filename: string, callback: (data: string) => void) { * fs.readFile(filename, 'utf8', (err: any, data: string) => { * if (err) throw err; * * // Process data after current I/O phase * scheduleNextTick(() => { * const processedData = data.toUpperCase(); * callback(processedData); * }); * }); * } * * // Database operation coordination * function processDbResults(query: string, results: any[]) { * console.log('Processing database results'); * * // Defer heavy processing to next tick * scheduleNextTick(() => { * const processed = results.map(result => ({ * ...result, * processed: true, * timestamp: Date.now() * })); * * console.log(`Processed ${processed.length} results`); * }); * } * ``` * * @example * Event loop coordination patterns: * ```typescript * // Coordinate multiple async phases * async function coordinateEventLoop() { * const phases: string[] = []; * * phases.push('sync-start'); * * // Microtask phase * queueMicrotask(() => { * phases.push('microtask-1'); * }); * * // Promise microtask * Promise.resolve().then(() => { * phases.push('promise-microtask'); * }); * * // Next tick (after microtasks) * scheduleNextTick(() => { * phases.push('next-tick'); * * // Nested next tick * scheduleNextTick(() => { * phases.push('nested-next-tick'); * }); * }); * * // Another next tick * scheduleNextTick(() => { * phases.push('next-tick-2'); * }); * * phases.push('sync-end'); * * // Wait for all phases to complete * await new Promise(resolve => setTimeout(resolve, 10)); * * console.log(phases); * // ['sync-start', 'sync-end', 'microtask-1', 'promise-microtask', 'next-tick', 'next-tick-2', 'nested-next-tick'] * } * ``` * * @example * Resource cleanup and lifecycle management: * ```typescript * // Server resource cleanup * class ServerResource { * private connections: Set = new Set(); * private cleanupScheduled = false; * * addConnection(conn: any) { * this.connections.add(conn); * } * * removeConnection(conn: any) { * this.connections.delete(conn); * this.scheduleCleanup(); * } * * private scheduleCleanup() { * if (!this.cleanupScheduled) { * this.cleanupScheduled = true; * * // Cleanup after current I/O operations * scheduleNextTick(() => { * this.performCleanup(); * this.cleanupScheduled = false; * }); * } * } * * private performCleanup() { * // Remove dead connections * for (const conn of this.connections) { * if (conn.destroyed) { * this.connections.delete(conn); * } * } * } * } * * // Application lifecycle coordination * class ApplicationLifecycle { * private shutdownCallbacks: (() => void)[] = []; * * onShutdown(callback: () => void) { * this.shutdownCallbacks.push(callback); * } * * shutdown() { * console.log('Starting graceful shutdown'); * * // Execute shutdown callbacks in next tick * scheduleNextTick(() => { * this.shutdownCallbacks.forEach(callback => { * try { * callback(); * } catch (error) { * console.error('Shutdown callback error:', error); * } * }); * * // Final cleanup in next tick * scheduleNextTick(() => { * console.log('Graceful shutdown complete'); * process.exit(0); * }); * }); * } * } * ``` * * @example * Testing and development utilities: * ```typescript * // Flush all pending next tick operations * function flushNextTick(): Promise { * return new Promise(resolve => { * scheduleNextTick(resolve); * }); * } * * // Testing async behavior * async function testNextTickBehavior() { * const events: string[] = []; * * events.push('test-start'); * * scheduleNextTick(() => { * events.push('next-tick-1'); * }); * * scheduleNextTick(() => { * events.push('next-tick-2'); * }); * * // Wait for next tick operations to complete * await flushNextTick(); * await flushNextTick(); // Ensure nested operations complete * * console.log(events); * // ['test-start', 'next-tick-1', 'next-tick-2'] * } * * // Development debugging helper * function debugEventLoop(label: string) { * console.log(`${label}: sync`); * * queueMicrotask(() => { * console.log(`${label}: microtask`); * }); * * scheduleNextTick(() => { * console.log(`${label}: next-tick`); * }); * * setTimeout(() => { * console.log(`${label}: timeout`); * }, 0); * } * ``` * * @example * Performance optimization patterns: * ```typescript * // Batch operations for next tick processing * class NextTickBatchProcessor { * private pendingOperations: (() => void)[] = []; * private processing = false; * * addOperation(operation: () => void) { * this.pendingOperations.push(operation); * this.scheduleBatch(); * } * * private scheduleBatch() { * if (!this.processing) { * this.processing = true; * * scheduleNextTick(() => { * this.processBatch(); * this.processing = false; * }); * } * } * * private processBatch() { * const operations = [...this.pendingOperations]; * this.pendingOperations.length = 0; * * operations.forEach(operation => { * try { * operation(); * } catch (error) { * console.error('Batch operation error:', error); * } * }); * } * } * * // I/O intensive operation scheduling * function scheduleIOIntensiveWork(work: () => void) { * // Defer I/O work to next tick to avoid blocking current operations * scheduleNextTick(() => { * const startTime = Date.now(); * work(); * const duration = Date.now() - startTime; * * if (duration > 10) { * console.warn(`Long-running operation: ${duration}ms`); * } * }); * } * ``` * * @example * Cross-platform compatibility patterns: * ```typescript * // Universal next tick scheduler with fallback * function createUniversalNextTick() { * // Get the optimal scheduler for current environment * const scheduler = scheduleNextTick; * * return { * schedule: (task: () => void) => scheduler(task), * * // Promise-based variant * promise: (): Promise => { * return new Promise(resolve => { * scheduler(resolve); * }); * }, * * // Multiple task scheduling * scheduleAll: (tasks: (() => void)[]) => { * scheduler(() => { * tasks.forEach(task => { * try { * task(); * } catch (error) { * console.error('Scheduled task error:', error); * } * }); * }); * } * }; * } * * // Environment-aware scheduling * function getEnvironmentInfo() { * const hasProcessNextTick = typeof process?.nextTick === 'function'; * const hasSetImmediate = typeof setImmediate === 'function'; * * return { * environment: hasProcessNextTick ? 'node' : hasSetImmediate ? 'browser-advanced' : 'browser-basic', * scheduler: hasProcessNextTick ? 'process.nextTick' : hasSetImmediate ? 'setImmediate' : 'setTimeout', * supportsNextTick: true // Always supported through this utility * }; * } * ``` * * @remarks * **Event Loop Integration:** * - **Node.js**: Executes after current I/O phase, before next I/O polling cycle * - **Browsers**: Executes after current macrotask, similar to setImmediate timing * - **Universal**: Consistent "next tick" semantics across all platforms * - **Priority**: Lower than microtasks, higher than regular macrotasks * * **Platform-Specific Behavior:** * - **Node.js**: Uses `Promise.resolve().then(() => process.nextTick(task))` for I/O coordination * - **Modern Browsers**: Uses `setImmediate` for optimal next-tick semantics where available * - **Legacy Browsers**: Falls back to `setTimeout(0)` with inherent timing constraints * - **Web Workers**: Consistent behavior using available scheduling mechanisms * * **Performance Characteristics:** * - **Time Complexity**: O(1) for scheduling operation * - **Space Complexity**: O(1) per scheduled task * - **Node.js**: ~0.001ms scheduling overhead with precise I/O timing * - **Browser**: ~0.01ms with setImmediate, ~1-4ms with setTimeout fallback * * **Comparison with Alternatives:** * - **process.nextTick** (Node.js): Direct access, but Node.js specific * - **setImmediate**: Similar timing, but limited browser support * - **setTimeout(0)**: Universal but subject to minimum delays * - **queueMicrotask**: Executes earlier in different event loop phase * - **scheduleMacrotask**: Similar timing but different implementation priorities * * **Use Cases:** * - Server-side I/O operation coordination * - Resource cleanup and lifecycle management * - Database operation sequencing * - Event loop phase coordination * - Testing and debugging async behavior * - Performance optimization through deferred execution * - Cross-platform next-tick semantics * - Application shutdown and cleanup procedures * * **Best Practices:** * - Use for operations that should run after current I/O phase * - Prefer for server-side applications requiring I/O coordination * - Ideal for cleanup operations and resource management * - Combine with error handling for robust task execution * - Use in testing utilities to control async execution flow * - Consider for cross-platform applications requiring consistent timing * * **Node.js Specific Advantages:** * - **I/O Coordination**: Optimal timing relative to file system and network operations * - **Process Integration**: Leverages Node.js event loop characteristics * - **Server Performance**: Optimized for server-side application patterns * - **Memory Efficiency**: Minimal overhead with native process.nextTick * * **Browser Compatibility:** * - **Modern Browsers**: Uses setImmediate where available for optimal timing * - **Legacy Support**: Graceful fallback to setTimeout for universal compatibility * - **Worker Contexts**: Consistent behavior in Web Workers and Service Workers * - **Electron**: Follows appropriate behavior based on main/renderer process context */ export declare const scheduleNextTick: Fn<[task: Fn<[], void>], void>;