node.js - nodejs - 将流从工作线程发送回主线程
问题描述
我一直试图将在我的程序中完成的一些工作分开在不同的线程中。其中一个函数需要将流返回到主线程,但我遇到以下异常:
Error
at MessagePort.<anonymous> ([worker eval]:12:16)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
From previous event:
at PoolWorker.work (node_modules/node-worker-threads-pool/src/pool-worker.js:22:12)
at DynamicPool.runTask (node_modules/node-worker-threads-pool/src/pool.js:110:47)
at DynamicPool.exec (node_modules/node-worker-threads-pool/src/dynamic-pool.js:51:17)
at renderToPdf (src/modules/templates/render2.js:27:14)
at Context.<anonymous> (test/modules/templates/render.test.js:185:68)
我试图构建一个最小的例子来重现我想要实现的目标。基本上,我需要的是向主线程发回一个可读流。在这个例子中,我也有一个例外:
为了有一个工作线程池,我专门使用库node-worker-threads-pool动态池。在里面我正在尝试转换html
为PDF。但我需要以某种方式将流返回到主线程。
const os = require('os');
const { DynamicPool } = require('node-worker-threads-pool');
const Pool = new DynamicPool(os.cpus().length);
async function convertToPDF(html) {
return await Pool.exec({
task: function() {
const Promise = require('bluebird');
const pdf = require('html-pdf');
const { html } = this.workerData;
const htmlToPdf = (html, renderOptions) => {
const options = {
format: 'Letter',
};
return pdf.create(html, Object.assign(options, renderOptions || {}));
};
return Promise.fromNode((cb) => htmlToPdf(html, {}).toStream(cb));
},
workerData: {
html,
},
});
}
convertToPDF('<div>Hello World!</div>')
.then((resp) => console.log('resp', resp))
.catch((err) => console.error('err', err));
err DataCloneError: function() {
if (this.autoClose) {
this.destroy();
}
} could not be cloned.
at MessagePort.<anonymous> ([worker eval]:12:16)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
您知道我该如何实现这一目标吗?
PS:我知道 IO 操作在工作线程中的性能不如它们在 nodejs 主线程中,但我需要这样做以避免这些操作锁定主线程。
解决方案
简短版:你不能。
node 中的 IPC 是通过一些黑盒处理的,但是我们知道消息对象在发送之前被序列化,并且在收到后被反序列化:你不能序列化 aStream
因为它基于底层级别(套接字、文件描述符、自定义读取并编写无法序列化/反序列化的函数等)。
所以你不得不交换可序列化的数据。
看一下html-pdf
我认为转换程序的一种简单方法是使用pdf.toBuffer
:与其尝试将 a 发送Stream
到主线程并在主线程中读取它以获得 a Buffer
,不如将 a 发送Buffer
到主线程而不是按原样使用它。
希望这可以帮助。
推荐阅读
- python - 为什么每个进程都会多次创建同一个对象?
- python - 弹出链表的最后一个元素时出现意外输出
- python-3.x - 将 varBinds 中的 OID 转换为 MIB 的最有效方法
- java - 在 JNI 函数中,当我就地更改从 Java 代码传递的数组时,数组不会修改
- javascript - 如何修改此代码以创建听写应用程序?
- c# - 如何在不点击 Unity 中的输入字段的情况下输入单词
- c - 修改内核参数(不允许 mmap 操作,EPERM)
- c++ - 计算 N 组交集的快速算法
- python - 构建和编译 keras 顺序模型时出现“列表索引超出范围”
- r - R - 如何在同一列中按每小时不同的分钟数计算值