Вопрос

I'm somehow new to nodejs and child processes and coming into some trouble now within my application. Something about the background: I have a nodejs-Websocket-Server working that loads a HTML page to any user thats is connecting. If the user is pressing a button on the HTML it sends a message to the server, that it should start an image capturing process (as a child process in node). So you can compare that to some kind of an infinite loop that runs in the child. So far so good, that works for me.

But now, if the user presses the button again, the child process should be stopped, so the image capture wont go any further. My problem is, that i have no idea how to stop the child process from the main process without killing it completly (the user should be able to start the loop again).

This is a snippet from the main process ("start" is either true or false, depending on if the user has pressed the start-button. Everytime the user clicks the button "start" changes its state):

var aCapLive = child.fork(__dirname + "/cp_capture_liveimg_async.js");  //Livebild
if (start) aCapLive.send(start);
else aCapLive.send(start);

And this is from the child:

var i = 0;
process.on("message", function(message)
{
    while(message)
    {
        console.log("CP aCapLive received message: Iteration " + i++);
    }
    console.log("CP aCapLive is going to exit now...");
    process.exit();
}

Obviously this doesnt work for me, because I'm running in my loop and cant detect any changes in "message". I would be very thankful if anyone had some ideas :)

Это было полезно?

Решение

Your code, as you have it, will never receive more than one message because it immediately goes into an infinite loop which never returns control to the event loop. The message variable is never going to magically change, and, since node is single-threaded, there is no possible way for the child to exit unless the very first message evaluated to false.

I think you're wanting something more like this:

var i = 0;
process.on("message", function(message)
{
    if(message)
    {
        console.log("CP aCapLive received message: Iteration " + i++);
    }
    else
    {
        console.log("CP aCapLive is going to exit now...");
        process.exit();
    }
});

If you want an infinite loop, you have to return control to the event loop after every iteration. This will allow a chance for new messages to come in. Example:

var _message;
var _running = false;
process.on("message", function (message)
{
    _message = message; // update the _message var when a new one comes in
    if (!_running) // this just prevents multiple loops from being started.
    {
        _running = true;
        run();
    }
});

var i = 0;
function run ()
{
    if(_message)
    {
        console.log("CP aCapLive received message: Iteration " + i++);
        setImmediate(run); // <-- this causes an infinite non-blocking loop
    }
    else
    {
        console.log("CP aCapLive is going to exit now...");
        process.exit();
    }
}

If message is going to be the same every time, what you actually want is a toggle system as such:

var _message = false;
process.on("message", function ()
{
    _message = !_message; // update the _message var when a new one comes in
    if (_message)
        run();
});

var i = 0;
function run ()
{
    if(_message)
    {
        i++;
        if (i % 10000 === 0)
            console.log("CP aCapLive received message: Iteration " + i);
        setImmediate(run); // <-- this causes an infinite non-blocking loop
    }
    else
    {
        console.log("CP aCapLive is going to exit now...");
        process.exit();
    }
}

Here's the parent process code I used to test it:

var childProcess = require('child_process');

var proc = childProcess.fork('child.js');
proc.send(true);
setTimeout(function () { proc.send(true); }, 4000); // send second message

Output:

CP aCapLive received message: Iteration 10000
CP aCapLive received message: Iteration 20000
CP aCapLive received message: Iteration 30000

... full output omitted for brevity ...

CP aCapLive received message: Iteration 1660000
CP aCapLive received message: Iteration 1670000
CP aCapLive received message: Iteration 1680000
CP aCapLive is going to exit now...

Другие советы

I made some bugfixing, so now I can start and stop the loop as often as I wish (replacing process.exit() with clearImmediate(id) so the process can be executed again and again):

var _message;
var _running = false;
var i = 0;

process.on("message", function (start)
{
    _message = start; // update the _message var when a new one comes in
    if (!_running) // this just prevents multiple loops from being started.
    {
        _running = true;
        run();
    }
});


function run ()
{
    if(_message)
    {
        console.log("CP aCapLive received message: Iteration " + i++);
        var id = setImmediate(run); // <-- this causes an infinite non-blocking loop
    }
    else
    {
        console.log("CP aCapLive is going to exit now...");
        _running = false;
        clearImmediate(id);
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top