Control Flow Expressions#
In a Control Flow workflow, tasks are not linked. A task reads the outputs of earlier tasks through expressions written between {{ and }} in its input and output rows. The engine evaluates each expression with MathJS ↗, not JavaScript.
Reading a Value#
An expression names a task with $ and its block name, followed by the output: {{ $<block name>.<output name> }}. For an output name with spaces, write {{ $<block name>["<output name>"] }}.
| Written | Reads |
|---|---|
$<block name>.<output> | An output of a task that already ran in the same branch or in an enclosing branch. |
$this.<output> | In an output row, a value that the task itself emitted. |
$scope.<name> | A value of an enclosing branch: the For iterator, the Foreach item, the Try..Catch error message, a function argument, or a value written by an output row named $scope.<name>. |
$global.<name> | A value written by an output row named $global.<name>. The controller keeps it after the branch ends. |
Table 1: Names an expression can read
The name after $ is the block name, stored in the workflow as the task name, not the block ID. The designer gives a new block a default name made of the task name, _, and four hexadecimal characters. A name that matches no task that already ran in the branch or in an enclosing branch fails the expression with Undefined symbol $<name>, and the branch ends. An output that the task did not emit gives no value. A row that holds only one expression passes the value with its own type, and text around expressions makes the row a text, so File {{ $onFile.FileName }}: {{ $onFile.Size }} bytes needs no operator.
When Expressions Are Evaluated#
- Settings - applied when the branch that holds the task is built, before any task of the branch runs. An expression in a setting reaches the task as text, unless the task evaluates that setting itself (Table 2). When a task has an input with the same name as a setting, write the expression in the input row.
- Input rows - evaluated just before the task runs. When a row fails, the controller logs
Failed to emit values to task '<task ID>' because '<message>'and the branch ends. - Output rows - evaluated just after the task emits. When a row fails, the controller logs
Failed to process outputs from task '<task ID>' because '<message>'.
| Task | Setting that the task evaluates when it runs |
|---|---|
| Control Flow - Condition | condition of each branch |
| Control Flow - TryCatch | variableName of the catch branch |
| Control Flow - Throw | Error Text |
| Log Message | Default Message, in RawText mode |
Table 2: Settings that accept an expression
Expression Language#
MathJS looks like JavaScript in places, but it is not:
- Combine tests with
and,or, andnot (...).&&,||, and!fail withFailed to parse expression '<expression>': Value expected (char <n>). - Compare with
==and!=, and write text in double quotes, for example"today's total". - Call a method on a value, for example
{{ $readFile.Content.split(",") }}. MathJS has nosplitfunction, sosplit(...)fails withUndefined function split. - Build an object in a row, for example
{{ {"FileName": $onFile.FileName} }}. - Count array positions from 0:
{{ $readList.Items[0] }}is the first item. - Write the escape
"\n"to split text into lines. A line break entered in a row reaches the evaluator as a space.
A condition, and a row of type Boolean, convert the result to a Boolean: true, t, yes, y, and 1, in any case, are true, and any other value is false. Compare the value, {{ $onFile.Size > 0 }}, instead of testing it bare. In Control Flow, the Condition task takes the place of Switch, which is available only in Data Flow.
Row Types#
Each row has a data type, and the engine converts the result of the row to it:
| Type | Conversion |
|---|---|
Any | None. Text around expressions is joined with each value written as JSON, so a text value keeps its quotes. |
String | The value as text. An object becomes [object Object]; use stringify to write it as JSON. |
Integer, Long, Decimal | A number. Text that does not start with a number fails with Unable to convert '<value>' to integer or to decimal. |
DateTime | A date, from a date text or from an epoch number in seconds or milliseconds. |
Object | An object or an array as it is. Text is parsed as JSON, so plain text such as reading.csv fails as not valid JSON. |
Table 3: Conversion by row type
Converter Functions#
A converter runs as a function inside an expression. When the controller prepares its first Control Flow workflow, it registers as functions the converters of its tasks libraries that declare an input type, an output type, and parameters, and logs each one as Registering function: <signature>. The core tasks package registers the following:
| Function | Value and result | Parameters, in order |
|---|---|---|
stringify | object to string | spaces |
stringToBase64 | string to string | None |
stringToEntityInstance | string to object | entityType, identifier, customType |
jsonata | any to any | expression |
isEmpty | any to any | resultType |
epochToDateTime | any to string | None |
now | any to string | format, timezone |
toTime | string to long | None |
Table 4: Converter functions
Pass the value first and the parameters after it, for example {{ jsonata($readFile.Content, "orders[0].id") }}. The engine converts the value to the value type before the call, and the result to the result type after it. So stringToBase64(42) encodes the text "42", and stringify parses a text value as JSON before writing it. Any other converter name fails with Undefined function <name>. For the parameters, see Converters.
Common Mistakes#
- Block ID instead of block name - the expression fails with
Undefined symbol, as it does after a block is renamed and the expressions that read it are not. - Reading a task placed later, in a sibling branch, or in a branch that has ended - write the value to
$global.<name>or$scope.<name>instead. - A bare value as a condition - compare it, so that the expression gives a Boolean.
- An expression in a setting that the task does not evaluate - the task receives the text as written.
- Plain text in an
Objectrow - type the rowString. {{ }}in the expression of the Generic Expression Evaluator task - write that expression over the input names of the task, without{{ }}and without$.