如何通过 worker_thread.Worker 传递类实例并使用函数?

9
为了更好地理解,我想通过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 }) });

正如您所看到的,工作者调用了名为process.js的脚本。让我们看一下。

process.js

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

let { obj } = workerData;

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

parentPort.postMessage('DONE');

正如您所知,此代码会抛出错误:TypeError: obj.c is not a function。实际上,在查看Worker线程文档(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函数,但我不知道该如何以不同的方式做到这一点。
我希望您能帮助我。谢谢您提前花费的时间。
1个回答

10
问题在于数据被作为普通对象(没有原型)在父进程和工作进程之间发送。因此,要再次将其转换为类,在工作进程中需要获取类代码并重新分配原型。
首先,您可以将类代码放入自己的模块中,以便可以将其导入到父进程和工作进程中。然后,在工作进程中,您可以将原型分配给获取的对象。
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');
    

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

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');
    

谢谢您的时间。实际上,我正在尝试第一种解决方案,但它不起作用。我已经正确地执行了它,但它仍然不起作用,并再次抛出TypeError: obj.c is not a function。我不知道为什么,但是``Òbject.SetPrototypeOf()```似乎在这里无效。对于您的第二个解决方案,我应该创建一个新的类构造函数来初始化一个新对象吗?我希望能够使用第一种方法,因为我操作了一个重型类实例,如果可以只设置原型,那将会更轻便。 - Helloïs
1
@Helloïs - 我犯了一个错误。我打错了字。应该是 Object.setPrototypeOf(obj, NewObj.prototype);。试一下吧。它需要是你的类的原型,而不是类本身。 - jfriend00
走吧!!! 它运行得非常好。感谢您的时间@jfriend00 - Helloïs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接