可以防止node.js工作者退出主进程

问题描述 投票:0回答:1

我正在使用nodejs 12,这个问题与https://nodejs.org/api/worker_threads.html有关我知道工作人员正在与主JS“线程”共享相同的过程;我仍然想知道是否有一种方法可以防止工作程序代码中的任何错误导致主进程崩溃。

我想使用辅助线程而不是分叉的进程,但是此问题将成为阻止程序。

worker.js

const { parentPort } = require( "worker_threads");

let i = 0;
setInterval(() => {
  parentPort.postMessage({ hello: "world" });
  i++;
  if (i > 5) {
    throw new Error('Hello'); // imagine here some error that hasn't been caught
  }
}, 200);

setInterval(() => {
  parentPort.postMessage({ foo: "bar" });
}, 600);

index.js

const { Worker } = require("worker_threads");
const worker = new Worker("./worker.js");

worker.on("error", (err) => {
  console.error(err);
});

worker.on("exit", () => {
  console.log('Worker exited')
});

worker.on("message", msg => {
  console.log(msg)
});

Output

➜ node index.js
{ hello: 'world' }
{ hello: 'world' }
{ foo: 'bar' }
{ hello: 'world' }
{ hello: 'world' }
{ hello: 'world' }
{ foo: 'bar' }
{ hello: 'world' }
Error: Something happened
    at Timeout._onTimeout (/Users/micael/Desktop/crashing/worker.js:10:11)
    at listOnTimeout (internal/timers.js:549:17)
    at processTimers (internal/timers.js:492:7)
Worker exited
javascript node.js web-worker worker worker-thread
1个回答
-1
投票

worker中的错误不会使主线程崩溃。主进程退出的原因是,一旦工作线程退出,就不再有其他待处理事件可供事件循环处理。这与常规主脚本相同,例如:

// index.js
console.log('hello');
// this scripts exits here

如果运行上面的简单脚本,您将看到node.js在脚本末尾退出主进程。这是正常现象。

为了证明这一点,您的主线程还有其他事情要做:

// index.js
const { Worker } = require("worker_threads");
const worker = new Worker("./worker.js");

worker.on("error", (err) => {
  console.error(err);
});

worker.on("exit", () => {
  console.log('Worker exited')
});

worker.on("message", msg => {
  console.log(msg)
});

setInterval(() => console.log('main is running'), 500);

工作线程崩溃后,您将发现主线程继续运行。


其他答案

从您的评论看来,您想要的不是让主线程继续运行,而是让工作线程继续运行。根据javascript处理未捕获错误的方式的性质,这是不可能的:解释器将仅记录错误并退出。解释器退出将导致线程终止。

如果工作线程死后,如果要让第二个setTimeout继续,则需要在单独的线程中运行它:

worker1.js:

const { parentPort } = require( "worker_threads");

let i = 0;
setInterval(() => {
  parentPort.postMessage({ hello: "world" });
  i++;
  if (i > 5) {
    throw new Error('Hello'); // imagine here some error that hasn't been caught
  }
}, 200);

worker2.js:

setInterval(() => {
  parentPort.postMessage({ foo: "bar" });
}, 600);
index.js

index.js:

const { Worker } = require("worker_threads");
const worker1 = new Worker("./worker.js");
const worker2 = new Worker("./worker.js");

worker1.on("error", (err) => {
  console.error(err);
});

worker1.on("exit", () => {
  console.log('Worker exited')
});

worker1.on("message", msg => {
  console.log(msg)
});

worker2.on("error", (err) => {
  console.error(err);
});

worker2.on("exit", () => {
  console.log('Worker exited')
});

worker2.on("message", msg => {
  console.log(msg)
});

或者,您可以在主线程中运行第二个setInterval:

worker.js:

const { parentPort } = require( "worker_threads");

let i = 0;
setInterval(() => {
  parentPort.postMessage({ hello: "world" });
  i++;
  if (i > 5) {
    throw new Error('Hello'); // imagine here some error that hasn't been caught
  }
}, 200);

index.js:

const { Worker } = require("worker_threads");
const worker = new Worker("./worker.js");

worker.on("error", (err) => {
  console.error(err);
});

worker.on("exit", () => {
  console.log('Worker exited')
});

worker.on("message", msg => {
  console.log(msg)
});

setInterval(() => {
  parentPort.postMessage({ foo: "bar" });
}, 600);
© www.soinside.com 2019 - 2024. All rights reserved.