javascriptnode.jsnode-worker-threads

Why worker threads aren't working when creating an class instance from other file?


I have this typescript file:

import { Worker, WorkerOptions, isMainThread, parentPort } from "worker_threads";
import path from "path";

export class SimpleWorker {
    private worker: any;

    constructor() {
        if (isMainThread) {
            console.log('Resolved Path:', path.join(__filename));

            const resolvedPath = path.join(__filename)

            this.worker = this.worker = new Worker(resolvedPath, {
                execArgv: /\.ts$/.test(resolvedPath) ? ["--require", "ts-node/register"] : undefined,
            });

            this.worker.on('message', (message: any) => {
                console.log(message);
            });

            this.worker.on('error', (error: any) => {
                console.log('Error from worker:', error);
            });

            this.worker.on('exit', (code: any) => {
                console.log('Worker has exited:', code);
            });

        } else {
            parentPort.postMessage('Hello from worker thread');
        }
    }
}

const simpleWorker = new SimpleWorker();

When executing the file using: npx ts-node examples/simple_worker.ts It will print:

Resolved Path: /home/user1/code/playground/examples/simple_worker.ts
Hello from worker thread
Worker has exited: 0

Now, when I remove the line const simpleWorker = new SimpleWorker(); from simple_worker.ts file.

And create another file called "test_worker.ts"

import { SimpleWorker } from './simple_worker';

const main = new SimpleWorker();

When executing this file using: npx ts-node examples/test_worker.ts It will print:

Resolved Path: /home/user1/code/playground/examples/simple_worker.ts
Worker has exited: 0

The threading didn't work.. why?


Solution

  • Because in the first approach, The simple_worker.ts creates an instance. So when you register the worker using simple_worker.ts, the following things happen.

    Creates Instance -> constructor runs -> Goes to else part -> posts message

    But in the second approach, You have removed the const simpleWorker = new SimpleWorker();part. So when you register the worker using simple_worker.ts, No instance will be created, constructor won't run.

    How to fix?

    It depends on your usage and requirements, But the simplest way is to pass the file (which init the instance ) as an argument.

    export class SimpleWorker {
        private worker: any;
    
        constructor( filepath: string ) {
            if (isMainThread) {
                console.log('Resolved Path:', path.join(filepath));
    
                const resolvedPath = path.join(filepath)
                // rest of your code
    
            } else {
                parentPort.postMessage('Hello from worker thread');
            }
        }
    }
    
    

    then,

    import { SimpleWorker } from './simple_worker';
    
    // Passing this file as arg, coz here only we creates the instance
    const main = new SimpleWorker(__filename);