---
pkg: '@nocobase/plugin-workflow-loop'
---


# Цикл

## Введение

Цикл — это синтаксическая конструкция, аналогичная `for`/`while`/`forEach` в языках программирования. Вы можете использовать узел цикла, когда необходимо повторить определённые операции заданное количество раз или для элементов какой-либо **коллекции** данных (массива).

## Установка

Это встроенный **плагин**, его установка не требуется.

## Создание узла

В интерфейсе настройки **рабочего процесса** нажмите кнопку с плюсом («+») в потоке, чтобы добавить узел «Цикл»:

![Создание узла цикла](https://static-docs.nocobase.com/b3c8061a66bfff037f4b9509ab0aad75.png)

После создания узла цикла будет сгенерирована внутренняя ветка цикла. Вы можете добавить любое количество узлов в эту ветку. Эти узлы могут использовать не только переменные из контекста **рабочего процесса**, но и локальные переменные из контекста цикла, например, объект данных, обрабатываемый в текущей итерации, или индекс итерации (индекс начинается с `0`). Область видимости локальных переменных ограничена только внутренними узлами цикла. При наличии вложенных циклов вы можете использовать локальные переменные конкретного цикла на каждом уровне.

## Настройка узла

![20241016135326](https://static-docs.nocobase.com/20241016135326.png)

### Объект цикла

Цикл по-разному обрабатывает различные типы данных объекта цикла:

1.  **Массив**: Это наиболее распространённый случай. Обычно вы можете выбрать переменную из контекста **рабочего процесса**, например, несколько результатов данных из узла запроса или предварительно загруженные данные отношений «один-ко-многим». Если выбран массив, узел цикла будет перебирать каждый элемент массива, присваивая текущий элемент локальной переменной в контексте цикла для каждой итерации.

2.  **Число**: Если выбранная переменная является числом, оно будет использоваться как количество итераций. Значение должно быть положительным целым числом; отрицательные числа не будут запускать цикл, а дробная часть числа будет игнорироваться. Индекс счётчика цикла в локальной переменной также является значением объекта цикла. Это значение начинается с **0**. Например, если число объекта цикла равно 5, то объект и индекс в каждой итерации будут последовательно: 0, 1, 2, 3, 4.

3.  **Строка**: Если выбранная переменная является строкой, её длина будет использоваться как количество итераций, при этом каждый символ строки будет обрабатываться по индексу.

4.  **Другие**: Значения других типов (включая объекты) рассматриваются как объекты цикла для однократной обработки и будут выполняться только один раз. Обычно в таких случаях использование цикла не требуется.

Помимо выбора переменной, вы также можете напрямую вводить константы для числовых и строковых типов. Например, ввод `5` (числовой тип) приведёт к выполнению узла цикла 5 раз. Ввод `abc` (строковый тип) приведёт к выполнению узла цикла 3 раза, обрабатывая символы `a`, `b` и `c` соответственно. В инструменте выбора переменных выберите желаемый тип для константы.

### Условие цикла

Начиная с версии `v1.4.0-beta`, добавлены опции, связанные с условиями цикла. Вы можете включить условия цикла в настройках узла.

**Условие**

Аналогично настройке условий в узле «Условие», вы можете комбинировать конфигурации и использовать переменные из текущего цикла, такие как объект цикла, индекс цикла и т. д.

**Время проверки**

Подобно конструкциям `while` и `do/while` в языках программирования, вы можете выбрать, когда проверять условие: до начала каждой итерации цикла или после её завершения. Проверка условия после итерации позволяет сначала выполнить другие узлы внутри тела цикла, а затем проверить условие.

**При невыполнении условия**

Подобно операторам `break` и `continue` в языках программирования, вы можете выбрать выход из цикла или переход к следующей итерации.

### Обработка ошибок во внутренних узлах цикла

Начиная с версии `v1.4.0-beta`, если узел внутри цикла не выполняется (из-за несоблюдения условий, ошибок и т. д.), вы можете настроить дальнейший ход **рабочего процесса**. Поддерживаются три способа обработки:

*   Выход из **рабочего процесса** (аналогично `throw` в программировании)
*   Выход из цикла и продолжение **рабочего процесса** (аналогично `break` в программировании)
*   Переход к следующему объекту цикла (аналогично `continue` в программировании)

По умолчанию выбрано «Выход из **рабочего процесса**», но вы можете изменить это по мере необходимости.

## Пример

Например, при оформлении заказа необходимо проверить наличие каждого товара в заказе. Если товара достаточно на складе, его количество уменьшается; в противном случае товар в детализации заказа помечается как недействительный.

1.  Создайте три **коллекции**: Товары <-(1:m)-- Детали заказа --(m:1)-> Заказы. Модель данных выглядит следующим образом:

    **Коллекция «Заказы»**
    | Название поля          | Тип поля                     |
    | ---------------------- | ---------------------------- |
    | Детали заказа          | Один-ко-многим (Детали заказа) |
    | Общая стоимость заказа | Число                        |

    **Коллекция «Детали заказа»**
    | Название поля | Тип поля              |
    | ------------- | --------------------- |
    | Товар         | Многие-к-одному (Товар) |
    | Количество    | Число                 |

    **Коллекция «Товары»**
    | Название поля   | Тип поля           |
    | --------------- | ------------------ |
    | Название товара | Однострочный текст |
    | Цена            | Число              |
    | Остаток         | Целое число        |

2.  Создайте **рабочий процесс**. В качестве триггера выберите «Событие **коллекции**» и укажите **коллекцию** «Заказы» для срабатывания «При добавлении записи». Также необходимо настроить предварительную загрузку данных отношений для **коллекции** «Детали заказа» и **коллекции** «Товары» в рамках этих деталей:

    ![Узел цикла_Пример_Настройка триггера](https://static-docs.nocobase.com/0086601c2fc0e17a64d046a4c86b49b7.png)

3.  Создайте узел цикла и выберите объект цикла как «Данные триггера / Детали заказа», что означает обработку каждой записи в **коллекции** «Детали заказа»:

    ![Узел цикла_Пример_Настройка узла цикла](https://static-docs.nocobase.com/2507becc32db5a9a0641c198605a20da.png)

4.  Внутри узла цикла создайте узел «Условие», чтобы проверить, достаточно ли товара на складе:

    ![Узел цикла_Пример_Настройка узла условия](https://static-docs.nocobase.com/a6d08d15786841e1a3512b38e4629852.png)

5.  Если товара достаточно, в ветке «Да» создайте узел «Вычисление» и узел «Обновить запись», чтобы обновить запись соответствующего товара с рассчитанным уменьшенным остатком:

    ![Узел цикла_Пример_Настройка узла вычисления](https://static-docs.nocobase.com/8df3604c71f8f8705b1552d3ebfe3b50.png)

    ![Узел цикла_Пример_Настройка узла обновления остатка](https://static-docs.nocobase.com/2d84baa9b3b01bd85fccda9eec992378.png)

6.  В противном случае, в ветке «Нет» создайте узел «Обновить запись», чтобы обновить статус детализации заказа на «недействительный»:

    ![Узел цикла_Пример_Настройка узла обновления детализации заказа](https://static-docs.nocobase.com/4996613090c254c69a1d80f3b3a7fae2.png)

Общая структура **рабочего процесса** показана ниже:

![Узел цикла_Пример_Структура рабочего процесса](https://static-docs.nocobase.com/6f59ef246c1f19976344a7624c4c4151.png)

После настройки и активации этого **рабочего процесса**, при создании нового заказа, система автоматически проверит наличие товаров в деталях заказа. Если товара достаточно, его количество будет уменьшено; в противном случае товар в детализации заказа будет помечен как недействительный (чтобы можно было рассчитать корректную общую стоимость заказа).