【发布时间】:2020-11-05 12:38:54
【问题描述】:
我最近读到了 Node 的“worker_threads”模块,它允许在多个线程中并行执行 Javascript 代码,这对于 CPU 密集型操作很有用。 (注意:这些不是 Chrome 在浏览器中制作的网络工作者)
我正在构建一个功能,我需要在不阻塞浏览器的情况下执行大量 Postgres INSERT。
问题是: 在我实例化 worker 的 Javascript 文件中,我不允许导入任何内容,包括本地 Node 模块或 NPM 库(如 Knex.js),这是执行数据库所必需的查询。我收到一条错误消息:Cannot use import statement outside a module 只要文件被执行。
我尝试将工作代码放在另一个文件中,并在顶部使用 import 语句(同样的错误)。我尝试将 Knex 对象提供给 workerData,但它无法克隆非原生 JS 对象。
我没有想法 - 如果我们无法导入任何 NPM 库,有谁知道如何在工作线程中与数据库交互?!?!
// mainThread.js
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
import knex from 'knex'; // --> *** UNCAUGHT EXCEPTION: Cannot use import statement outside a module ***
if (isMainThread) {
module.exports = async function runWorker (rowsToInsert = []) {
return new Promise((resolve, reject) => {
const worker = new Worker(__filename, { workerData: { rowsToInsert } });
worker.on('message', (returningRows) => resolve(returningRows));
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
});
});
};
} else {
const { rowsToInsert } = workerData;
return knex('table').insert(rowsToInsert)
.then((returningRows) => {
parentPort.postMessage({ data: returningRows });
});
}
我正在关注这个网页的教程:https://blog.logrocket.com/use-cases-for-node-workers/
【问题讨论】:
-
是的,您可以为此使用 workerThreads,但它可能不是必需的或有用的。数据库本身就是它自己的进程。因此,所有 nodejs 进程正在做的就是以非阻塞、异步的方式向它发送网络请求。 nodejs 不太可能做任何会从 workerThreads 中受益的 CPU 密集型操作。
-
仅供参考,在编写 workerThread 代码时,如果您将 workerThread 代码放在自己的文件中并且不要将主线程代码与 workerThread 代码混合在同一个文件中,我发现它 200% 更清晰、更清晰、更容易调试.这样做时你不应该需要
if (isMainThread) {}。此外,当您将代码清晰地分成两个文件时,对代码在哪里运行的整体知识理解会更容易理解。 -
感谢您的解释!我感觉合理! @jfriend00
-
@jfriend00 顺便说一句,如果您有任何其他见解 - 在尝试使用 Node 进行大容量插入(例如,每次摄取最多 100 万行)时,我可以使用哪些其他工具?
-
nodejs 不是你的挑战。挑战将是对数据库进行 100 万次插入。数据库将是那里的瓶颈,而不是 nodejs。如需进一步帮助,您可能想就您正在使用的特定数据库以及您要插入的具体内容提出一个新问题,然后也许真正了解该数据库的人可以谈论最有效的获取方法所有这些数据都进入数据库。同样,这并不是真正的 nodejs 问题,而是如何以最佳方式使用数据库。
标签: node.js node-cluster worker-thread import-module node-worker-threads