Function

What Is a Function node in Node-RED?

In Node-RED, a function node allows you to write custom JavaScript code to process message objects in your flow. It's used for specific tasks that can't be accomplished with the standard built-in nodes alone. When you write custom JavaScript in a function node, this code gets executed every time a message passes through the node.

In Node-RED, a function should either return an object, which is a message object, or nothing at all. Returning other data types instead of an object will cause an error. By default, the function node returns the message object unchanged, passing the data as it is to further nodes.

Ideally, the function node should have the message object returned at the end of the code written within it. Placing the return statement in the middle of the code may result in incomplete execution of the remaining code.

If the function node needs to perform an asynchronous action before sending a message, it cannot use the return statement to send the message at the end of the function. Instead, in such cases, you must use node.send(), as shown below:

// Simulate an asynchronous operation with setTimeout
setTimeout(() => {
// After 2 seconds, create a message object with some data
const message = { payload: "Async operation complete" };
// Send the message to subsequent nodes
node.send(message);
}, 2000);

Additionally, if you need to pass a message object mid-script within a function node to subsequent nodes, you can utilize node.send() for this purpose while continuing the execution of the remaining code, as shown below:

// Extract data from the incoming message
const inputData = msg.payload;

// Perform some processing
const processedData = inputData * 2;

// Send a message object with the processed data
node.send({ payload: `Processed data: ${processedData}` });

// Continue executing the rest of the code...

// Example of further processing...
if (processedData > 100) {
node.warn("High processed data value detected!");
} else {
node.log("Processed data value within normal range.");
}

// Return the modified message object
return msg;

If you don't want the function to pass anything to subsequent node, you can do this by returning null in the function node.

By default, a function node has a single output, but you can configure it to have multiple outputs in the setup tab with the output property. You can then send the message to each output using an array, placing them in order of which output they should go to.

var msg1 = { payload: 1 };
var msg2 = { payload: [3,45,2,2,4] };
var msg3 = { payload: {"name":"bob"} };
var msg4 = { payload: "This is string" };
return [msg1, msg2, msg3, msg4];

Function Node Different Tabs

In the function node, we have four different types of tabs, each with its unique use case:

Setup

  • Output: This property allows you to configure how many outputs the function node will have.
  • Timeout: This property Allows you to define how long the function node can run before an error is raised. By default, if set to 0, no timeout is applied.
  • Modules: This property Allows you to add or import additional modules into Function nodes, and they will be automatically installed when the flow is deployed. However, in the - settings, you'll need to set 'functionExternalModules' to 'true'.

On Start

In this tab, you can provide code that will run whenever the node is started. This can be used to set up any state the Function node requires.

On Message

This is the tab where you can provide the JavaScript code that will execute when it receives a message passed by another nodes.

On Stop

This tab allows you to add code to clean up any ongoing tasks or close connections before the flow is redeployed.

Logging events

When a function node needs to log something, it can utilize the following methods:

  • node.log(): This is used for general logging purposes.
  • node.warn(): This method is used to log warnings.
  • node.error(): This is used to log errors.

Messages logged using node.warn() and node.error() will be sent to the debug tab.

To view messages logged using node.log(), you can check the command from where you started Node-RED. If you're running it under an app like PM2, it will have its own method for displaying logs. On a Raspberry Pi, the install script adds a node-red-log command that shows the log. If you're using FlowFuse Cloud, you can find the logged messages in the Instance's Node-RED logs tab.

Node-RED Objects Accessible in Function Node

The following Node-RED objects can be accessed in a function node:

  • node: This object encapsulates properties and methods used for customizing and interacting with nodes in a flow.
  • context: The node’s local context.
  • flow: The flow scope context.
  • global: The global scope context.
  • RED: This object provides module access to the Node-RED runtime API.
  • env: This object contains the get method to access environment variables.

Use-cases and examples

  1. Custom logic: Sometimes your flow might require very specific logic that can’t be achieved using existing nodes. Function node allow you to implement this custom logic.

In the example flow below, we have a function that converts temperature data, simulated using an inject node with a random number, from Celsius to Fahrenheit. Additionally, it performs other formatting.

  1. Conditional Routing: When dealing with a broad range of conditions that require intricate logic for each case, the switch node may fall short. In such scenarios, using a function node with multiple outputs can be benificial.

In the example flow below, we have an inject node generating a random number and sending it to the function node. We've set up the function node to evaluate the received numeric value and perform conditional routing based on predefined ranges, sending the message to different outputs accordingly.

Node Documentation

A JavaScript function to run against the messages being received by the node.

The messages are passed in as a JavaScript object called msg.

By convention it will have a msg.payload property containing the body of the message.

The function is expected to return a message object (or multiple message objects), but can choose to return nothing in order to halt a flow.

The On Start tab contains code that will be run whenever the node is started. The On Stop tab contains code that will be run when the node is stopped.

If the On Start code returns a Promise object, the node will not start handling messages until the promise is resolved.

Details

See the online documentation for more information on writing functions.

Sending messages

The function can either return the messages it wants to pass on to the next nodes in the flow, or can call node.send(messages).

It can return/send:

  • a single message object - passed to nodes connected to the first output
  • an array of message objects - passed to nodes connected to the corresponding outputs

Note: The setup code is executed during the initialization of nodes. Therefore, if node.send is called in the setup tab, subsequent nodes may not be able to receive the message.

If any element of the array is itself an array of messages, multiple messages are sent to the corresponding output.

If null is returned, either by itself or as an element of the array, no message is passed on.

Logging and Error Handling

To log any information, or report an error, the following functions are available:

  • node.log("Log message")
  • node.warn("Warning")
  • node.error("Error")

The Catch node can also be used to handle errors. To invoke a Catch node, pass msg as a second argument to node.error:

node.error("Error",msg);

Accessing Node Information

The following properties are available to access information about the node:

  • node.id - id of the node
  • node.name - name of the node
  • node.outputCount - number of node outputs

Using environment variables

Environment variables can be accessed using env.get("MY_ENV_VAR").