Loop over data в n8n: Полное руководство по обработке массивов и циклов
В n8n, платформе автоматизации рабочих процессов, концепция «Loop over data» (циклическая обработка данных) является фундаментальной для выполнения повторяющихся операций над элементами коллекций, такими как массивы JSON, списки или строки с разделителями. В отличие от традиционного программирования, где циклы реализуются через конструкции for или while, n8n использует нодо-центричный подход, где циклы создаются путем связывания и настройки специализированных узлов. Понимание и правильное применение циклов критически важно для построения эффективных, масштабируемых и надежных автоматизаций.
Основные узлы для организации циклов
n8n предоставляет несколько ключевых узлов, предназначенных для итерации по данным. Выбор узла зависит от источника данных, требуемой логики и способа интеграции цикла в общий workflow.
Узел «Split In Batches» (Разделить на партии)
Этот узел предназначен для обработки больших массивов данных по частям (батчам). Он автоматически разбивает входящий массив на меньшие группы заданного размера и запускает последующий узел или цепочку узлов для каждой группы отдельно. Это предотвращает таймауты и перегрузку API при работе с тысячами записей.
- Параметр «Batch Size»: Определяет количество элементов в одной партии.
- Параметр «Options» → «Reset»: Если включен, workflow начнет обработку с первой партии при каждом запуске. Если выключен, n8n запомнит, на какой партии остановился предыдущий запуск (полезно для обработки длинных задач, которые могут прерваться).
- Параметр «Mode»: «Run Once for Each Item» (запустить один раз для каждого элемента) или «Run Once for All Items» (передать весь массив в следующую ноду).
- Особенность: Все ноды, следующие за Loop Over Items, выполняются заново для каждого элемента. Это важно учитывать при проектировании workflow, чтобы избежать лишних операций (например, аутентификации в API на каждой итерации).
- Условие: Задается через Expression Editor. Например, для постраничной навигации условие может проверять, есть ли в ответе API поле «nextPage».
- Шаг 1: Узел «Google Sheets» → операция «Get All Rows». На выходе получаем массив объектов (строк таблицы).
- Шаг 2: Узел «Loop Over Items» (или «For Each»). Он подключен к выходу Google Sheets. В его настройках оставляем режим по умолчанию.
- Шаг 3: Внутри цикла (после Loop Over Items) размещаем узел «Email (SMTP)». В полях «To», «Subject», «Body» используем Expression, чтобы подставить данные из текущего элемента цикла (например,
{{$json['Email']}},{{$json['Name']}}). - Шаг 4: Workflow запускается. Для каждой строки из таблицы будет выполнен узел отправки email с уникальными данными.
- Шаг 1: Узел «CRM Read» получает список клиентов, требующих обновления.
- Шаг 2: Узел «Split In Batches». Batch Size устанавливаем в 90 (с запасом от лимита).
- Шаг 3: После Split In Batches размещаем узел «HTTP Request» (или родной узел CRM), настроенный на операцию обновления. Этот узел получит на вход массив из 90 элементов. Если в HTTP Request активирован режим «Batch», он автоматически сделает 90 отдельных запросов. Важно: между батчами можно добавить узел «Wait» или «Schedule» для паузы в 60 секунд, чтобы соблюсти лимит RPM (запросов в минуту).
- Шаг 1: Узел «HTTP Request» выполняет первый запрос к API (например, на страницу 1). В ответе приходит массив товаров первой страницы и, например, параметр «hasMore: true».
- Шаг 2: Узел «DO WHILE». Подключаем к нему цепочку: нода для обработки данных страницы (например, сохранения в базу) и нода «HTTP Request» для запроса следующей страницы. В настройках DO WHILE задаем условие продолжения цикла на языке выражений, например:
{{$json['hasMore'] === true}}. - Шаг 3: Внутри цикла второй HTTP Request должен динамически формировать URL или параметры запроса для следующей страницы, используя данные из предыдущего ответа (например,
{{$node['HTTP Request'].json['nextPageToken']}}). - Сетевая задержка: Внутри цикла выполняются синхронные HTTP-запросы. Используйте асинхронные операции, если их поддерживает целевой узел, или увеличивайте параллельность через настройки (где это возможно).
- Отсутствие батчинга: Обработка тысяч элементов в цикле «Loop Over Items» по одному всегда медленнее, чем группировка в батчи и использование batch-режима узлов.
- Тяжелые операции внутри цикла: Проверьте, нет ли внутри цикла операций, которые можно вынести наружу (загрузка файлов, сложные вычисления).
Узел «HTTP Request» в режиме «Batch»
Стандартный узел HTTP Request может работать в режиме батча. Когда ему на вход подается массив элементов, и в настройках активирована опция «Batch», узел автоматически выполнит отдельный HTTP-запрос для каждого элемента массива. Это упрощает массовые операции с API без явного использования узла Split In Batches.
Узел «Loop Over Items» (Цикл по элементам)
Этот узел является универсальным инструментом для итерации. Он принимает массив данных и для каждого элемента этого массива выполняет всю последующую цепочку узлов, подключенную после него. Это самый гибкий способ реализации сложной логики для каждого элемента.
Узел «For Each» (Для каждого)
Функционально очень похож на «Loop Over Items» и часто используется как его синоним в более новых версиях n8n. Он также итерирует по элементам входного массива, запуская подключенный к нему подворкфлоу (subworkflow).
Узел «DO WHILE» (Цикл с условием)
Этот узел реализует цикл с условием продолжения. Он повторяет выполнение подключенной к нему цепочки узлов до тех пор, пока заданное условие не станет ложным (false). Полезен для случаев, когда количество итераций неизвестно заранее (например, постраничная навигация по API).
Практические примеры и шаблоны использования
Пример 1: Отправка персонализированных email каждому контакту из списка
Цель: Взять список контактов из Google Sheets и отправить каждому контакту индивидуальное email-сообщение через SMTP или сервис типа SendGrid.
Пример 2: Пакетное обновление записей в CRM через API с разделением на батчи
Цель: Обновить статус для 5000 клиентов в CRM, но API CRM имеет лимит 100 запросов в минуту.
Пример 3: Постраничная загрузка всех данных из REST API
Цель: Загрузить все товары из магазина, API которого возвращает данные постранично (пагинация).
Ключевые принципы и лучшие практики
При работе с циклами в n8n необходимо придерживаться ряда правил для обеспечения стабильности и производительности workflow.
| Принцип | Описание | Пример/Как реализовать |
|---|---|---|
| Минимизация операций внутри цикла | Любая операция внутри цикла выполняется многократно. Вынос общих операций (аутентификация, загрузка справочников) за пределы цикла значительно ускоряет выполнение. | Узел аутентификации в API помещается ДО узла «Loop Over Items». Токен сохраняется в переменных workflow и используется внутри цикла. |
| Обработка ошибок | Ошибка на одной итерации цикла может остановить весь workflow. Необходимо предусматривать обработку исключений. | Использовать узел «Error Trigger» или настраивать политику повторных попыток (Retry) на узлах внутри цикла. Можно логировать ошибки без прерывания потока, используя ветвление. |
| Работа с памятью и лимитами | Обработка очень больших массивов «в лоб» может исчерпать ресурсы сервера. | Всегда используйте «Split In Batches» для массивов, превышающих несколько тысяч элементов. Настройте «Batch Size» в соответствии с лимитами целевых API и вашего инстанса n8n. |
| Использование Expression для доступа к данным | Внутри цикла доступ к данным текущей итерации осуществляется через специальные переменные. | Для узла «Loop Over Items» используйте {{$json}} для доступа ко всему элементу или {{$json['fieldName']}} для доступа к конкретному полю. Для доступа к данным из узлов, выполненных на предыдущих итерациях, используйте {{$node['NodeName'].item.json}}. |
| Сохранение контекста между итерациями | Иногда необходимо накапливать данные или счетчик между итерациями. | Используйте узлы «Set» или «Function» для записи данных в переменные workflow ({{$workflow.variables.myArray}}). Эти переменные доступны для чтения и записи на всех итерациях. |
Отладка workflow с циклами
Отладка циклических процессов имеет свою специфику. В режиме выполнения (Execution Debug) n8n позволяет просматривать данные на входе и выходе каждого узла для каждой итерации в отдельности. Важно проверять не только первую итерацию, но и несколько последующих, чтобы убедиться в корректности динамически формируемых параметров. Использование узла «Code» (Function или Function Item) для вывода логов (console.log) внутри цикла является мощным инструментом для отслеживания состояния данных на разных этапах.
Интеграция циклов с другими узлами n8n
Циклы часто комбинируются с узлами для условной логики («IF»), преобразования данных («Set», «Code»), и агрегации результатов. Например, после цикла, который собирает данные из нескольких источников, можно разместить узел «Merge» для объединения результатов или узел «Aggregate» для суммирования значений. Важно понимать структуру данных на выходе из цикла: обычно это массив результатов всех итераций, который может потребовать выравнивания (flatten).
Ответы на часто задаваемые вопросы (FAQ)
В чем разница между «Loop Over Items» и «Split In Batches»?
«Loop Over Items» выполняет подключенные после него узлы для КАЖДОГО элемента массива поочередно. «Split In Batches» сначала разбивает массив на группы (батчи), а затем передает каждую группу (массив элементов) на следующую ноду для обработки. Если следующая нода (например, HTTP Request) поддерживает batch-режим, она сама выполнит итерации внутри батча. Таким образом, Split In Batches — это инструмент управления объемом данных за одну итерацию основного потока, а Loop Over Items — инструмент явной итерации на уровне workflow.
Как остановить или прервать цикл досрочно?
Прямого аналога «break» из языков программирования в узлах цикла n8n нет. Однако можно смоделировать прерывание, изменив условие в узле «DO WHILE» так, чтобы на следующей итерации оно вернуло false. В узле «Loop Over Items» досрочная остановка возможна только через ошибку (Error Trigger) или путем установки флага в переменных workflow и проверки его в начале каждой итерации через узел «IF», который будет перенаправлять поток в пустую ветку.
Почему мой workflow с циклом выполняется очень медленно?
Основные причины медленной работы циклов:
Как получить сводный результат после выполнения всех итераций цикла?
Данные, произведенные на каждой итерации узла «Loop Over Items», автоматически собираются в массив и передаются далее по workflow после завершения цикла. Вы можете подключить к выходу узла «Loop Over Items» любой узел для обработки этого итогового массива (например, «Code» для преобразования, «Spreadsheet File» для записи в Excel). Для узла «Split In Batches» итоговый результат также представляет собой объединенный массив результатов всех батчей.
Можно ли создавать вложенные циклы (nested loops)?
Да, вложенные циклы возможны. Для этого нужно поместить второй узел «Loop Over Items» или «For Each» внутрь цепочки узлов, выполняемой первым циклом. Важно тщательно проектировать такие workflow, так как общее количество итераций будет равно произведению размеров внешнего и внутреннего массивов, что может привести к экспоненциальному росту времени выполнения. Всегда используйте батчинг и вынос общих операций на максимально высокий уровень.
Как обращаться к данным из предыдущих узлов внутри цикла?
Используйте Expression Editor и переменные. Для доступа к данным узла, который находится ДО цикла, но в той же ветке, используйте конструкцию вида {{$node['NodeName'].json}}. Для доступа к данным из узла, выполненного на ПРЕДЫДУЩЕЙ итерации того же цикла, такая конструкция не сработает. Вам необходимо передавать нужные данные через поток элементов (как часть $json) или сохранять/читать их из переменных workflow ($workflow.variables).
Добавить комментарий