# Node.status is not set on receiving message

**URL:** <https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915>\
**Category:** Developing Nodes\
**Created:** [2 December 2020 23:06 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915 "2020-12-02T23:06:44Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![JSONata](https://avatars.discourse-cdn.com/v4/letter/j/85e7bf/32.png) [@JSONata](https://discourse.nodered.org/u/JSONata)\
**Post date:** [2 December 2020 23:06 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915/1 "2020-12-02T23:06:44Z")

</div>

We have a fairly simple node, executing an external program. Upon incomming message node should update its status and display "executing". However node status doesn't change. Only in the end node status is "All operations finished".

Sourcecode of testnode.js

```auto
"use strict";

const execFile = require('child_process').execFileSync;

let externalProg = __dirname + "/wait.sh";

module.exports = function (RED) {

    function testnode(config) {

        RED.nodes.createNode(this, config);

        var node = this;        

        node.on('input', function (msg, send, done) {

            // For maximum backwards compatibility, check that send exists.

            // If this node is installed in Node-RED 0.x, it will need to

            // fallback to using `node.send`

            send = send || function () { node.send.apply(node, arguments) }

            done = done || function () { if (arguments.length > 0) node.error.apply(node, arguments) }

            node.status({fill:"yellow",shape:"dot",text: "Executing ..."});

            

            try {

                let res = execFile(externalProg, { encoding: "utf8" }).trim();

                msg.payload=res;

            }

            catch (error) {

                console.log(error);

                done("Error executing external file. Execute permisson set?", msg);

                node.status({fill:"red",shape:"dot",text: "Error executing file ..."})

                return;

            }

            send(msg);

            // If an error is hit, report it to the runtime

            node.status({fill:"green",shape:"dot",text: "All operations finished."})

            if (done) {

                done();

            }

        });

    }

    RED.nodes.registerType("testnode", testnode);

}

```

If you want to try it, you can use package.json und testnode.html from [Reading from serial. Works in sample-js file, but when running in node-red serial port gets closed](https://discourse.nodered.org/t/reading-from-serial-works-in-sample-js-file-but-when-running-in-node-red-serial-port-gets-closed/36347)

Script simulating an external program

```auto
#!/bin/bash
sleep 5s
echo "Done waiting"

```

Flow:

![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/f/4ff2e17592ea38b0a2d9439d3b282e61b0e7e806.png)

```json
[{"id":"d24c6e9f.28db78","type":"inject","z":"b451655f.5db818","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":400,"y":280,"wires":[["465016d8.ef75a"]]},{"id":"465016d8.ef75a","type":"testnode","z":"b451655f.5db818","name":"testnode","serialport":"/dev/serial0","x":640,"y":280,"wires":[["f96506af.bb3e48"]]},{"id":"f96506af.bb3e48","type":"debug","z":"b451655f.5db818","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":280,"wires":[]}]

```

What am I doing wrong? Why is there no node status displaying "Executing..."?

PS: I know maximum execution time for a node is 15 seconds. The real script will take 10 seconds at max, so that won't be a problem.

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [2 December 2020 23:14 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915/2 "2020-12-02T23:14:47Z")

</div>

The problem comes because you are blocking the entire node.js process by using `execFileSync`. That prevents the runtime from fully processing the `node.status` call and getting the event to the editor to display the new status.

> [@JSONata](#):
>
> PS: I know maximum execution time for a node is 15 seconds. The real script will take 10 seconds at max, so that won't be a problem.

Where did you get that from? There is no 'maximum execution time' - however you really must not write code that blocks the whole node.js process for long periods. Use the async version of the function to allow the rest of the runtime (and your other flows) to continue operating.

---

<div class="post-metadata">

**Author:** ![JSONata](https://avatars.discourse-cdn.com/v4/letter/j/85e7bf/32.png) [@JSONata](https://discourse.nodered.org/u/JSONata)\
**Post date:** [2 December 2020 23:22 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915/3 "2020-12-02T23:22:43Z")

</div>

I don't understand why it prevents the node from fully processing. It calls node.status. So it should wait until node.status is finished and then continue executing the code in the following lines.

I've modified the example. Problem occurs even without execFileSync, but instead also with doing an active wait in a for loop. So how could it be modified that it works as expected? Input event listener should only finish when all code inside has finished.

New node:

```auto
"use strict";

module.exports = function (RED) {
    function testnode(config) {
        RED.nodes.createNode(this, config);
		var node = this;		

		node.on('input', function (msg, send, done) {
			// For maximum backwards compatibility, check that send exists.
			// If this node is installed in Node-RED 0.x, it will need to
			// fallback to using `node.send`
			send = send || function () { node.send.apply(node, arguments) }
			done = done || function () { if (arguments.length > 0) node.error.apply(node, arguments) }

			node.status({fill:"yellow",shape:"dot",text: "Executing ..."});
			
            console.log("Before loop");
			for(let i=0;i<399999999;)
			{
				if(i%10000000 == 0)
				{
					node.status({fill:"green",shape:"dot",text: "Connecting..."})
					console.log("Working");
				}
				
				i=i+1;
			}
			console.log("After loop");
            
			send(msg);
			// If an error is hit, report it to the runtime
			node.status({fill:"green",shape:"dot",text: "All operations finished."})

			if (done) {
				done();
			}
        });
    }
    RED.nodes.registerType("testnode", testnode);
}

```

Maximum execution time is from [JavaScript file : Node-RED](https://nodered.org/docs/creating-nodes/node-js)

> In 0.17 and later, the runtime will timeout the node if it takes longer than 15 seconds. An error will be logged and the runtime will continue to operate.

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [2 December 2020 23:29 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915/4 "2020-12-02T23:29:35Z")

</div>

> [@JSONata](#):
>
> I've modified the example. Problem occurs even without execFileSync, but instead also with doing an active wait in a for loop

Yes, because you've swapped one blocking piece of code, for another.

It is a really bad design pattern to do fully blocking code like this in node.js. That goes against the entire programming model that Node.js relies on.

You should use asynchronous actions whenever you are doing work that can take any significant time - that allows the node.js event loop to continue processing other work in the "background".

> [@JSONata](#):
>
> Maximum execution time is from [JavaScript file : Node-RED](https://nodered.org/docs/creating-nodes/node-js)

You are reading the section of the docs related to closing the Function node - when the 'close' event is triggered, the node has a maximum of 15 seconds to complete its work. That is completely unrelated to handling messages

---

<div class="post-metadata">

**Author:** ![JSONata](https://avatars.discourse-cdn.com/v4/letter/j/85e7bf/32.png) [@JSONata](https://discourse.nodered.org/u/JSONata)\
**Post date:** [2 December 2020 23:34 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915/5 "2020-12-02T23:34:23Z")

</div>

You write, that I'm blocking the whole node.js process.  
If created a sample flow where a simple function node just simulates some heavy work and wants to output a yellow status when executed and green status when finished.  
 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/e/4edb34ba0f06a90a4d1816c876173b8fca325fe2.png)

```auto
node.status({fill:"yellow",shape:"dot",text: "Executing ..."});
for(let i=0;i<399999999;)
			{
				if(i%10000000 == 0)
				{
					node.status({fill:"green",shape:"dot",text: "Connecting..."})
					console.log("Working");
				}
				
				i=i+1;
			}
node.status({fill:"green",shape:"dot",text: "All operations finished."})			
return msg;

```

Flow:

```auto
[{"id":"f2604c45.158b6","type":"inject","z":"b451655f.5db818","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":900,"y":200,"wires":[["86ce0cda.9df9"]]},{"id":"86ce0cda.9df9","type":"function","z":"b451655f.5db818","name":"","func":"node.status({fill:\"yellow\",shape:\"dot\",text: \"Executing ...\"});\nfor(let i=0;i<399999999;)\n\t\t\t{\n\t\t\t\tif(i%10000000 == 0)\n\t\t\t\t{\n\t\t\t\t\tnode.status({fill:\"green\",shape:\"dot\",text: \"Connecting...\"})\n\t\t\t\t\tconsole.log(\"Working\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\ti=i+1;\n\t\t\t}\nnode.status({fill:\"green\",shape:\"dot\",text: \"All operations finished.\"})\t\t\t\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1100,"y":200,"wires":[["9d7bf051.1c7388"]]},{"id":"9d7bf051.1c7388","type":"debug","z":"b451655f.5db818","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1280,"y":200,"wires":[]}]

```

Even this single function blocks whole node red process. So how would that function be rewritten not to block whole Node-RED Process?

---

<div class="post-metadata">

**Author:** ![JSONata](https://avatars.discourse-cdn.com/v4/letter/j/85e7bf/32.png) [@JSONata](https://discourse.nodered.org/u/JSONata)\
**Post date:** [2 December 2020 23:41 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915/6 "2020-12-02T23:41:35Z")

</div>

I also have about \> 200 Nodes in my complete homeautomation system. Timing is sometimes very important.  
Suppose an action is checked every second via an inject node and thus 60 times per minute.  
Due to heavy systemload for a few seconds these \> 200 nodes need together more than 1s execution time. Than timer event will me missed and in this minute it will be executed less than 60 times. This is not good, because completly different code lead to missing this event.

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [2 December 2020 23:45 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915/7 "2020-12-02T23:45:04Z")

</div>

Once approach would be to identify how you can slice the work up into smaller batches and use `setImmediate` to schedule the next batch - allowing the node.js event loop to make progress on any other events that need handling.

```auto

node.status({fill:"yellow",shape:"dot",text: "Executing ..."});

function processBatch(start) {
    for (let i=start;i<start+1000;i++) {
        // do something
        if(i%10000000 == 0)
        {
             node.status({fill:"green",shape:"dot",text: "Connecting..."})
             console.log("Working");
         }
    }
    if (start+1000 < 399999999) {
        setImmediate(function() {
            processBatch(start+1000);
        })
    } else {
       node.status({fill:"green",shape:"dot",text: "All operations finished."})			
       node.send(msg)
    }
}
processBatch(0);

return;

```

> [@JSONata](#):
>
> I also have about \> 200 Nodes in my complete homeautomation system. Timing is sometimes very important.  
> Suppose an action is checked every second via an inject node and thus 60 times per minute.  
> Due to heavy systemload for a few seconds these \> 200 nodes need together more than 1s execution time. Than timer event will me missed and in this minute it will be executed less than 60 times. This is not good, because completly different code lead to missing this event.

All the more reason not to write code the starves the node.js event loop from being able to do anything.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [16 December 2020 23:45 UTC](https://discourse.nodered.org/t/node-status-is-not-set-on-receiving-message/36915/8 "2020-12-16T23:45:05Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
