它可以在单独的线程中执行?"/>
有没有办法将 node.js 类转换为 worker,以便它可以在单独的线程中执行?
我有一个耗时的任务要在 node.js 服务器上执行。我想测试它在单独的线程中运行时的性能。我想从工人那里公开课程,而不必手动编写每个部分的代码。是否有可以执行此操作的节点内部功能或模块?谢谢
class RunInWorker {
constructor (starta, startb) {
this.sum = starta + startb;
}
addSync(a, b) {
return a + b + this.sum;
}
async addAsync(a, b) {
await (new Promise((resolve) => { setTimeout(resolve, 3000); }));
return a + b + this.sum;
}
}
/** @type {\RunInWorker} */
let worker = new require('./wrap-worker.js')(RunInWorker, [5, 5]);
(async () => {
console.log(worker);
console.log(await worker.addSync(3, 4), 'should be', 17);
console.log(await worker.addAsync(3, 8), 'should be', 21);
})();
我目前正在将课程转换为字符串,而不是即时创建一个工人,但我认为这不是最好的方法......
// wrap-worker.js
const { Worker, isMainThread } = require('worker_threads');
function WrapWorker(OBJECT, OBJECT_ARGS) {
if (isMainThread) {
let workerCode = `
const { parentPort, workerData } = require('worker_threads');
let OBJECT = ` + OBJECT.toString() + `
let INSTANCE = new OBJECT(...workerData);
parentPort.on('message', async function (data) {
if (data.method) {
let method = INSTANCE[data.method];
if (typeof method === 'function') {
let response;
if (method.constructor.name === 'AsyncFunction') response = await method.apply(INSTANCE, data.arguments);
else response = method.apply(INSTANCE, data.arguments);
parentPort.postMessage({ rid: data.rid, valid: 1, response: response });
} else {
parentPort.postMessage({ rid: data.rid, valid: 0 });
}
}
});`;
let instance = new Worker(workerCode, { eval: true, workerData: OBJECT_ARGS });
let methodsProxy = {};
let methods = Object.getOwnPropertyNames(OBJECT.prototype);
let rid = 0;
let requests = [];
for (let mid in methods) {
let methodId = methods[mid];
methodsProxy[methodId] = function () {
return new Promise((resolve, reject) => {
rid++;
requests[rid] = { resolve: resolve, reject: reject };
instance.postMessage({ method: methodId, arguments: Array.from(arguments), rid: rid });
});
};
}
instance.on('message', function (data) {
if (data.rid) {
if (data.valid) requests[data.rid].resolve(data.response);
else requests[data.rid].reject();
delete requests[data.rid];
}
});
return methodsProxy;
}
}
module.exports = WrapWorker;
回答如下:
// wrap-worker.js
const { Worker } = require('worker_threads');
function WrapWorker(OBJECT, OBJECT_ARGS) {
if (require('worker_threads').isMainThread) {
const workerCode = `
const { parentPort, workerData } = require('worker_threads');
const OBJECT = ${OBJECT.toString()};
const instance = new OBJECT(...workerData);
parentPort.on('message', async (data) => {
try {
const method = instance[data.method];
if (typeof method === 'function') {
const response = await method.apply(instance, data.arguments);
parentPort.postMessage({ rid: data.rid, valid: true, response });
} else {
parentPort.postMessage({ rid: data.rid, valid: false });
}
} catch (error) {
parentPort.postMessage({ rid: data.rid, valid: false });
}
});
`;
const instance = new Worker(workerCode, { eval: true, workerData: OBJECT_ARGS });
const methodsProxy = {};
const methods = Object.getOwnPropertyNames(OBJECT.prototype);
let rid = 0;
const requests = {};
for (const methodId of methods) {
methodsProxy[methodId] = (...args) =>
new Promise((resolve, reject) => {
rid++;
requests[rid] = { resolve, reject };
instance.postMessage({ method: methodId, arguments: args, rid });
});
}
instance.on('message', (data) => {
const request = requests[data.rid];
if (request) {
if (data.valid) {
request.resolve(data.response);
} else {
request.reject();
}
delete requests[data.rid];
}
});
return methodsProxy;
}
}
module.exports = WrapWorker;
更多推荐
有没有办法将 node.js 类转换为 worker,以便它可以在单独的线程中执行?
发布评论