简体   繁体   中英

In Node JS, I have an async operation that does not resolve. How do I use worker thread to abort it?

Say I have an async operation like so:

    async () => {
       await longTask().then(result => console.log(result));
    }

Let's say longTask is unpredictable. It hangs and does not resolve some of the time.

I understand that we can't just abort an async operation.

I looked into worker threads so that I can spawn a worker to run this async operation and terminate it if need be.

Unfortunately when I tried it, the whole program exits.

Is there a way for me to abort/terminate/cancel/kill a worker thread and just remove the async operation, without exiting the node app?

Thanks for your time.

Borrowing from the Node.js documentation on Cluster here , a possible approach can be the following:

Main.js

const { fork } = require('child_process');
const WORKER_PATH = 'PATH_TO_WORKER_JS';
const INTERVAL = 10000; // 10 seconds
let CHECKS = 0; // keep count of how many times you check for completion

const worker = fork(WORKER_PATH);

// send message to start the async process

worker.send({ start: true }, err => {
   if(err) { // handle error }
});

// check for completion on the worker

setTimeout(() => {
    worker.send({ checkIsDone: true }, err => {});
}, INTERVAL);

// listen for message from worker

function checkMsg(msg) {
   const { done } = msg;
   if(done) {
       // async process ended; kill the worker
       worker.kill('SIGKILL');
   } else {
      if(check > 10) {
         // checked 10 times for completion, 10 seconds apart; 
         // process not terminating so force kill
         worker.send('SIGKILL');
      } else {
         // setup another check in 10 seconds
         setTimeout(() => {
             worker.send({ checkIsDone: true }, err => {});
         }, INTERVAL);
      }
      CHECKS++;
   }
}

process.on('message', checkMsg);

Worker.js

let isDone = false;

async function indeterministicProcess() {

   // some long computation
   
   // finished
}

process.on('message', msg => {
    const { checkIsDone, start } = msg;
    if(start) { 
        // start your async process 
        interdeterministicProcess().then(() => (isDone = true)).catch(e => console.error(e));
    } else if(checkIsDone) {
       if(isDone) {
           // send done message to master
           process.send({ done: true}, err => {});
       } else {
          process.send({ done: false}, err => {});
       }

    }
});

This is an approach I have used a few times in the past and has worked for me really well. Hope this gives you some idea on how to implement this for your use case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM