如何通过worker_thread.Worker传递带有函数的类实例来使用函数?

Hel*_*oïs 10 javascript multithreading worker-thread node.js node-worker-threads

为了上下文化,我想通过 NodeJS“worker_thread”模块中的工作线程使用类实例函数。

在一个main.js文件中,我声明一个类并实例化一个新的 Worker,并通过选项传递新实例workerData

main.js

const { Worker } = require('worker_threads');

class obj {
    constructor() {
        this.a = "12";
        this.b = 42;
    }

    c() {
        return 'hello world';
    }
}

let newobj = new obj();
console.log({
    a: newobj.a,
    b: newobj.b,
    c: newobj.c()
});
//Output: { a: '12', b: 42, c: 'hello world' }

let worker = new Worker('./process.js', { workerData: { obj: newobj } });
worker.once('message', res => { console.log({ res }) });
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,工作人员调用了process.js脚本。让我们看看吧。

流程.js

const { parentPort, workerData } = require('worker_threads');

let { obj } = workerData;

console.log({
    a: obj.a,
    b: obj.b,
    c: obj.c()
});

parentPort.postMessage('DONE');
Run Code Online (Sandbox Code Playgroud)

如您所知,此代码会引发错误:TypeError: obj.c is not a function。事实上,在检查了 Worker Thread 文档(https://nodejs.org/dist./v10.22.0/docs/api/worker_threads.html#worker_threads_new_worker_filename_options)后,我发现 Worker 不可能是具有功能的对象。事实上,它可以工作,但所有功能都没有被克隆。 NodeJS 官方文档中worker_thread、workerData 选项定义的屏幕截图

我真的很困惑,因为我不知道如何解决这个问题。事实上,这个例子很简单,因为简化了复杂的情况,但就我而言,我绝对需要在process.js侧面调用 c 函数,但我不知道如何以不同的方式执行此操作。

我希望你能帮助我。在此先感谢您的时间。

jfr*_*d00 11

问题是数据在父进程和工作进程之间作为普通对象(没有原型)发送。因此,要再次将其放入类中,在工作线程中,您需要类代码并重新分配原型。

首先,您可以将类代码放入其自己的模块中,以便可以将其导入父级和工作线程中。然后,在worker中,您可以将原型分配给您获得的对象。

const { parentPort, workerData } = require('worker_threads');
let { obj } = workerData;
const NewObj = require('./newobj');
Object.setPrototypeOf(obj, NewObj.prototype);

console.log({
    a: obj.a,
    b: obj.b,
    c: obj.c()
});

parentPort.postMessage('DONE');
    
Run Code Online (Sandbox Code Playgroud)

另一种方法是导入类代码,然后为该类创建一个构造函数选项,该选项从普通对象中获取数据并用它初始化一个新的类实例。

const { parentPort, workerData } = require('worker_threads');
const NewObj = require('./newobj');

// create a NewObj from scratch and let it initialize itself from the object that
// was passed to our worker
let obj = new NewObj(workerData.obj);

console.log({
    a: obj.a,
    b: obj.b,
    c: obj.c()
});

parentPort.postMessage('DONE');
    
Run Code Online (Sandbox Code Playgroud)