josdejong / workerpool

Offload tasks to a pool of workers on node.js and in the browser
Apache License 2.0
2.08k stars 146 forks source link

Not executing function that depends on variable/function out of scope. #401

Closed J9B10 closed 1 year ago

J9B10 commented 1 year ago

Hello,

I recently saw this project on npm and found it very interesting because it makes it easy to send the function to a worker without the hassle of the nodejs pattern.

But I'm having difficulty because I came across an error where it says:

ReferenceError: 'var' is not defined
    at 'func' (eval at run (C:\MyApp\node_modules\workerpool\src\worker.js:105:11), <anonymous>:5:3)
    at Function.eval (eval at run (C:\MyApp\node_modules\workerpool\src\worker.js:105:11), <anonymous>:8:4)
    at Function.run (C:\MyApp\node_modules\workerpool\src\worker.js:106:12)
    at MessagePort.<anonymous> (C:\MyApp\node_modules\workerpool\src\worker.js:157:27)
    at [nodejs.internal.kHybridDispatch] (node:internal/event_target:807:20)
    at exports.emitMessage (node:internal/per_context/messageport:23:28)

I realized that this error happens because my function depends on variables outside the scope.

I'm new to javascript and I don't know how to solve this.

I saw the documentation for this module say that out-of-scope code cannot be executed by the worker.

I'm asking that if there is a way to make this happen it would be very good and would help a lot in several projects.

This is my code example:

// myApp.js as a "type": "module",;

import workerpool from 'workerpool';

const pool = workerpool.pool();

const numWorkers = 2;

// Independent Function: OK //;

async function add_A(value) {
    let sum = 0;
    for (let i = 0; i < value; i++) {
            sum += 1;
    }
    console.log("add_A sum =", sum);
}

// Function Depends on Out-of-Scope Variable: FAIL //;

let sum = 0;

async function add_B(value) {
    for (let i = 0; i < value; i++) {
        sum += 1;
    }
    console.log("add_B sum =", sum);
}

// Add Function //;

async function pool_add(func, params) {
    await pool
        .exec(func, [params]) // without ();
        .then(function (result) {
            console.log('result', result); // outputs;
        })
        .catch(function (err) {
            console.error(err);
        })
        .then(function () {
            pool.terminate(); // terminate all workers when done;
        });
}

// Workers Quantity Caller //;

for (let i = 0; i < numWorkers; i++) {
    // pool_add(add_A, 1000000000000);
    pool_add(add_B, 1000000000000);
}

To see the difference just change the comment between calling 'add_A' or 'add_B'.

If anyone knows how I can run workers this way I would appreciate it.

josdejong commented 1 year ago

To solve that, you can do two things: pass the variable along as one of the arguments, or create a dedicated worker and keep the state there.