Question:
Nodejs Query Solved: Interrupt NodeJS loop based on socket data

Problem

I am trying to terminate a long running loop in node.js using sockets.


I am emiting an event from react using socket.emit('eventName') and there is a socket.on('eventName') on server, which eventually suppose to update a boolean flag and terminate the running loop.


But when I emit an event, event emits but does not reflect at server end because loop is still running.


for(let i = 0; i < body.length; i++){

    /**

        Long Running loop which needs to be terminated based on socket event

    **/

}


It terminates or takes input from socket after the loop ends. But I need to terminate the loop while it is executing.


[Update]


let booleanFlag = false //default value of flag


Below function will be called from socket.on('eventName')


function cancelAPIRequest(){

    booleanFlag = true

}


This for loop which needs to be terminated, and will check the state of the variable 


"booleanFlag" at each iteration.

for(let i = 0; i < body.length; i++){

    if(!booleanFlag){

        // continues loop

    }else{

        return; // terminates loop

    }

}


Solution

The JavaScript engine being monothread, it executes your synchronous loop in one go, without giving any chance to any other processing to occur, including the handling of your socket event (of course it will be handled at some point, but after your synchronous loop has ended).


To give a chance to your event to change your flag value, and the latter to be picked up inside the loop, you need to "pause" that loop regularly, typically by introducing an async operation, e.g.:


// Inside an async function

async function someFunction() {

  for (let i = 0; i < body.length; i++) {

    await sleep(); // async step to enable other processing to occur

    if (!booleanFlag){ // flag may be updated externally during the sleep

        // continues loop

    } else {

        return; // terminates loop

    }

  }

}


function sleep(delayInMs = 0) {

  return new Promise((resolve) => {

    setTimeout(resolve, delayInMs);

  });

}


Answered by: >ghybs

Credit: >StackOverflow


Blog Links: 

>How do I customize controller actions in Laravel Jetstream?

>Run Laravel Project to Active Local Server

>How to show encrypted user id in URL in Laravel?

>How to fix Laravel LiveWire listener?


Nisha Patel

Nisha Patel

Submit
0 Answers