Iteration in Frends Processes

How to iterate using While, ForEach and Code Task shapes.

Iteration is a fundamental concept in process automation, allowing you to execute a set of actions repeatedly. In Frends, this is primarily achieved using the visual ForEach and While shapes. However, for more complex or self-contained logic, you can also perform iteration directly within a Code Task using standard C#.

This guide will walk you through all three methods to build robust and efficient iteration logic in your Frends Processes.

Prerequisites

To follow this guide, you will need an Editor role in your Frends environment to create and modify Processes. No other special permissions or connectors are required.

Method 1: Using the ForEach Shape

The ForEach shape is the standard, low-code approach for when you need to perform an action for every item in a known list or array. It is ideal for processing lines from a file or handling multiple order items from a single request.

It's important to note that ForEach shape cannot modify the iterated container's data directly or add or remove items during the iteration. You will need to build a copy of the data if needed, or handle each item to completion during the iteration to avoid duplication of data.

Input Data

For this example, let's assume we have a JSON array of simple objects. This could come from an API call, a database query, or be defined directly in the Process. We will use a Code Task to create a sample array.

{
    return new JArray(
        new JObject { {"id", 1}, {"value", "First Item"} },
        new JObject { {"id", 2}, {"value", "Second Item"} },
        new JObject { {"id", 3}, {"value", "Third Item"} }
    );
}

Have the Code Task assign the newly created JArray to variable named ItemsArray.

Creating example JArray with Code Task.

Configuring the ForEach Loop

To get started with the iteration, drag a ForEach shape onto the canvas. In the shape's settings, you'll need to provide the collection you want to iterate over in the Expression field. If you're using the Code Task from the previous step, the expression would be #var.ItemsArray.

Next, define a Variable name for the current item in the iteration. For example, you might call it currentItem. This variable will hold the data for one item at a time as the loop progresses through your collection.

Configuration of a ForEach shape, showing the Expression and Variable fields.

Processing Each Item

Inside the ForEach scope, you can add any logic you need to process the currentItem. You can access the item's data using the variable name you defined, like #var.currentItem.value.

For this example, let's use Assign Variable shape to collect the #var.currentItem.id value into variable named currentId. We can then use a Return shape inside the ForEach shape to return this value as the result for our ForEach iteration, by setting the Return shape's Expression field to value $"Processed item with ID: {#var.currentId}". The ForEach shape will collect the returned value from each iteration into a single array.

Full example in the editor, with the Return shape highlighted.

Final Result

The ForEach shape itself returns a #result reference value that is an array containing the value returned from each individual iteration. In our example, the final result would be an array of strings:

[
  "Processed item with ID: 1",
  "Processed item with ID: 2",
  "Processed item with ID: 3"
]
ForEach returns all results from the iteration as array.

Method 2: Using the While Shape

The While shape is used when the number of iterations is unknown or defined in other methods. The loop continues as long as a defined condition is true. A common use case is polling an external system until a task is complete.

While shape is also useful if you need to modify the contents of a list or array during the iteration, or add or remove elements, as you can set the condition more dynamically than for ForEach.

Initializing the Loop

Unlike ForEach, a While loop doesn't have a built-in collection to iterate over. You typically need to initialize variables that will be used in the loop's condition and logic. Let's use an Assign Variable shape to create a variable named counter, and initialize it to zero (0). This variable will be incremented within the While loop.

Configuring the While Loop

Start by dragging a While shape onto the canvas. In the Expression field, you'll define the condition that must equal to true for the loop to continue. For our example with an incrementing value, the expression would be #var.counter < 3.

Here's something crucial: you must set the Max iterations property. This is a mandatory safeguard to prevent infinite loops and will stop the Process with an error if the limit is reached. Think of it as your safety net.

Configuration of a While shape, showing the Expression and Max iterations fields.

Loop Logic and Terminating the Loop

Inside the While shape, you must include logic that will eventually cause the loop condition to become false. In our case, we need to increment the counter. Add a Code Task or Assign Variable shape inside the While loop and use an expression to increment the counter variable from the previous iteration.

Without reassigning the counter variable, you can use expression such as #var.counter++ or #var.counter = #var.counter + 1. By making the shape assign a variable, you can use #var.counter+1 as its value will be evaluated and assigned back to the counter variable.

Assign Variable shape used to increment the counter.

After incrementing the variable, the While shape must end to a Return shape. Set the Return shape's Expression field to value $"Number of processed items: {#var.counter}".

Final Result

The While shape returns only the value from the last successful iteration. In this example, after the loop terminates (when the counter is no longer less than 3), the #result reference value of the While shape will be "Number of processed items: 3".

Result of the While iteration is only the last result.

Method 3: Using the Code Task

For scenarios requiring complex data manipulation or high-performance loops without the overhead of multiple Task executions, you can perform iteration directly within a single Code Task using C#. This approach encapsulates the entire loop logic in one place.

Because debugging longer pieces of code from a Code Task is harder than from the While or ForEach shapes, Code Task should not replace major Process logic.

Unless set by the developer, iteration within Code Tasks will also not include safeguards or cancellation tokens that are built in to the iteration shapes. These may cause Process Instances or whole Frends Agents becoming unresponsive if created incorrectly. ForEach iteration is inherently safer to perform in code than While, which may cause infinite loop.

Input Data

We will use the same input data as in the ForEach example, which is a JArray created in a preceding Code Task.

Implementing the Loop in C#

Drag a Code Task onto the canvas. Inside the code editor, you can write standard C# loops such as foreach, for, or while to process the data. This example uses a foreach loop to iterate through the input array, transform each object, and collect the results in a new JArray.

{
    // Access the input array from a previous step
    var inputArray = #var.ItemsArray as JArray;
    
    if (inputArray == null)
    {
        return new JArray(); // Return empty array if input is null
    }
    
    var resultArray = new JArray();
    
    // Iterate through each item in the JArray
    foreach (var item in inputArray)
    {
        var id = item["id"];
        var value = item["value"];
    
        // Create a new object with transformed data
        var newObject = new JObject
        {
            ["processedId"] = $"item-{id}",
            ["originalValue"] = value,
            ["timestamp"] = DateTime.UtcNow
        };
    
        resultArray.Add(newObject);
    }
    
    // Return the new array containing all processed items
    return resultArray;
}

Make the Code Task assign a variable named ResultArray, for example.

Code Task performing iteration.

Final Result

The Code Task will execute the entire loop and return the final resultArray as its output. The assigned variable #var.ResultArray will be a single JArray containing all the transformed objects:

[
  {
    "processedId": "item-1",
    "originalValue": "First Item",
    "timestamp": "2023-10-27T10:30:00.123Z"
  },
  {
    "processedId": "item-2",
    "originalValue": "Second Item",
    "timestamp": "2023-10-27T10:30:00.124Z"
  },
  {
    "processedId": "item-3",
    "originalValue": "Third Item",
    "timestamp": "2023-10-27T10:30:00.125Z"
  }
]
Example result for iteration in Code Task.

Last updated

Was this helpful?