在本文中,我们讨论最新版本的Node.js(13.0)中Node和Worker Threads中并行性背后的基本概念。

并发与并行

长期以来,Node.js在并发方面表现出色。在最近发布的Node 13.0中,Node现在对并行性也有了稳定的答案。

并发可以看作是异步过程之间的切换,所有异步过程都轮流执行,并且在空闲时将控制权返回到事件循环。另一方面,并行性是进程分离并同时在多个线程上运行的能力。JavaScript中还有其他解决方案试图解决此问题。




主进程中发生javascript occurred in the main process错误怎么解决 电脑主进程出现javascript错误_主进程中发生javascript错误


主脚本

主脚本必须做三件事

  • 通过引用工作程序的js文件来创建工作程序。
const worker = new WorkerThread.Worker(join(__dirname, './worker.js'))
  • 向工人发送消息以启动工作。消息只是一个JavaScript对象,因此,如果您需要自定义工作程序的行为,则可以包括任何分类,数据等。
worker.postMessage({foo:"stuff"});
  • 注册对动作的响应。工作者的任何响应都将是消息事件,并返回一个对象。您可以返回字符串或更复杂的对象,并带有工作人员已执行的任何操作的结果。
worker.on('message', (message) =>{ //对响应进行处理}

现在,尝试将它们组合成脚本

const { join } = require('path');const WorkerThread = require('worker_threads');const THREAD_COUNT = 30;/ ** *运行修改THREAD_COUNT之前 * /(async () => {  //设置运行作业所需的任何数据。   const users = await getAllUsers();  //定义函数以处理工作人员传递的不同消息  function handleStatusReport(workerNumber, report) {    console.log(`the worker:${workerNumber} says`, report.body || report);  }  function handleWorkerFinished(worker, workerNumber, message) {    console.log(`done with ${JSON.stringify(message.body)}!`);    if (i < users.length) {      worker.postMessage(users[i]);      i += 1;    } else {      console.log(`Worker number ${workerNumber} completed working!`);    }  }  //提升第一批工作人员......再利用这些工人,让他们完成更多的工作  for (let j = 0; j < Math.min(THREAD_COUNT, users.length); j += 1) {    const worker = new WorkerThread.Worker(join(__dirname, './worker.js'));    console.log(`Running ${i} of ${users.length}`);    worker.postMessage(users[i]);    i += 1;   //听工作者的消息    worker.on('message', (messageBody) => {      //打开消息正文中的值,以支持不同类型的消息      if (messageBody.type === 'done') {        handleWorkerFinished(worker, j, messageBody);      } else {        handleStatusReport(j, messageBody);      }    });  }})();

工作者脚本

可以简单到

parentPort.on('message', async someObject => //一些使用对象的函数,可以通过返回给父工作器报告);

原本不需要报告;但这是个好习惯,它可以知道工作人员是否完成,失败或有选择地返回计算结果。

parentPort.postMessage({ type: 'done', body: {key: 'value'} });
parentPort.postMessage({ type: 'log', body: {message: 'something happened'} });

上面的示例具有一个type值为 done和 的属性 log。名称和值都是任意的-请记住,可以通过这种方式在工人和主人之间交换数据。另外,我应该注意,从工作程序向主服务器发送消息不会终止工作程序。因此,一个工人可以在执行期间发送许多消息。

这是针对工人的更全面的模板:

const { parentPort } = require('worker_threads');async function process(someObject) {  //在这里做很多处理...  //将状态更新发送给PRIMARY  parentPort.postMessage({ type: 'status', body: 'still working' });  //进行更多处理...  //将带有相关数据的最终消息发送回PRIMARY脚本  parentPort.postMessage({ type: 'done', body: {key: 'value'} });}//注册方法以对消息执行parentPort.on('message', async

补充说明

线程工作器直到最近才成为Node 13.0中的稳定功能。如果在运行旧版本的节点时发生任何错误,则值得通过使用--experimental-worker标志运行来启用线程工作器。

node --experimental-worker master.js

希望能对你有用。