Author: saqibkhan

  • Handle Uncaught Exceptions and Unhandled Rejections

    Tip:

    Properly handle uncaught exceptions and unhandled promise rejections to prevent application crashes.

    Example:

    javascriptCopy codeprocess.on('uncaughtException', (err) => {
    
    console.error('Uncaught Exception:', err);
    // Perform cleanup and exit or restart application
    }); process.on('unhandledRejection', (reason, promise) => {
    console.error('Unhandled Rejection:', reason);
    // Perform cleanup and exit or restart application
    });

    Reason: Helps in managing errors gracefully and avoiding abrupt crashes, though it is often better to fix the root causes of these issues.

  • Implement Graceful Shutdown

    Tip:

    Implement graceful shutdown procedures to ensure ongoing requests are completed before exiting.

    Example:

    javascriptCopy codeconst server = require('http').createServer((req, res) => {
    
    res.end('Hello World');
    }); server.listen(3000); function shutdown() {
    server.close(() => {
        console.log('Server closed');
        process.exit(0);
    });
    setTimeout(() => {
        console.error('Forcing shutdown');
        process.exit(1);
    }, 10000); // Force shutdown after 10 seconds
    } process.on('SIGTERM', shutdown); process.on('SIGINT', shutdown);

    Reason: Ensures that active connections are properly closed and resources are released before the application exits.

  • Use process.hrtime() for High-Resolution Timing

    Tip:

    Use process.hrtime() for accurate timing measurements in your application.

    Example:

    javascriptCopy codeconst start = process.hrtime();
    // Code to measure
    const end = process.hrtime(start);
    console.log(Execution time: ${end[0]} seconds and ${end[1] / 1e6} milliseconds);
    

    Reason: Provides high-resolution time measurements, useful for performance profiling and benchmarking.

  • Enable and Use the –trace-warnings Flag

    Tip:

    Use the --trace-warnings flag to get detailed stack traces for warnings, which can help diagnose issues more effectively.

    Example:

    bashCopy codenode --trace-warnings your-script.js
    

    Reason: Provides more context for warnings that could indicate potential issues in your code.

  • Manage Dependencies with Care

    Tip:

    Regularly audit and update your dependencies to avoid security vulnerabilities and ensure compatibility.

    Example:

    bashCopy code# Audit dependencies for vulnerabilities
    npm audit
    
    # Update outdated dependencies
    npm update
    

    Reason: Keeping dependencies up-to-date helps mitigate security risks and ensures compatibility with newer versions of Node.js.

  • Optimize Performance with cluster Module

    Tip:

    Use the cluster module to take advantage of multi-core systems by creating child processes that share the same server port.

    Example:

    javascriptCopy codeconst cluster = require('cluster');
    const http = require('http');
    const numCPUs = require('os').cpus().length;
    
    if (cluster.isMaster) {
    
    console.log(Master ${process.pid} is running);
    for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
    cluster.on('exit', (worker, code, signal) => {
        console.log(Worker ${worker.process.pid} died);
    });
    } else {
    http.createServer((req, res) => {
        res.writeHead(200);
        res.end('Hello, World!\n');
    }).listen(8000);
    console.log(Worker ${process.pid} started);
    }

    Reason: Clustering enables better CPU utilization and can handle more concurrent connections by distributing the load.

  • Utilize the worker_threads Module

    Tip:

    Use the worker_threads module to handle CPU-bound tasks by running JavaScript code in parallel threads.

    Example:

    javascriptCopy codeconst { Worker } = require('worker_threads');
    
    function runWorker(taskData) {
    
    return new Promise((resolve, reject) => {
        const worker = new Worker('./worker.js', { workerData: taskData });
        worker.on('message', resolve);
        worker.on('error', reject);
        worker.on('exit', (code) => {
            if (code !== 0) reject(new Error(Worker stopped with exit code ${code}));
        });
    });
    }

    Reason: worker_threads allow for parallel processing and can improve performance for CPU-intensive operations.

  • Leverage Streams for Large Data Handling

    Tip:

    Use streams to handle large files or data in chunks rather than loading everything into memory.

    Example:

    javascriptCopy codeconst fs = require('fs');
    const zlib = require('zlib');
    
    const readStream = fs.createReadStream('largeFile.txt');
    const writeStream = fs.createWriteStream('largeFile.gz');
    const gzip = zlib.createGzip();
    
    readStream.pipe(gzip).pipe(writeStream);
    

    Reason: Streams help manage memory efficiently and improve performance by processing data incrementally.

  • Use async/await for Asynchronous Code

    Tip:

    Transition from callback-based code to async/await to make asynchronous code more readable and maintainable.

    Example:

    javascriptCopy codeconst fs = require('fs').promises;
    
    async function readFile(filePath) {
    
    try {
        const data = await fs.readFile(filePath, 'utf8');
        return data;
    } catch (err) {
        console.error('Error reading file:', err);
    }
    }

    Reason: async/await simplifies asynchronous code by avoiding callback hell and making error handling more straightforward.

  • Using worker_threads for Parallel Processing

    Node.js 12 introduced the worker_threads module, allowing for parallel execution of JavaScript.

    javascriptCopy code// worker.js
    const { parentPort } = require('worker_threads');
    
    parentPort.on('message', (data) => {
    
    // Perform some computation
    parentPort.postMessage(data * 2);
    }); // main.js const { Worker } = require('worker_threads'); function runWorker(data) {
    return new Promise((resolve, reject) => {
        const worker = new Worker('./worker.js');
        worker.on('message', resolve);
        worker.on('error', reject);
        worker.postMessage(data);
    });
    } async function main() {
    try {
        const result = await runWorker(5);
        console.log('Worker result:', result);
    } catch (err) {
        console.error('Worker error:', err);
    }
    } main();

    Explanation:

    • worker_threads allows you to create parallel threads for computation.
    • Use postMessage to communicate between the main thread and worker threads.