n8n-loops

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

n8n Loops

n8n 循环机制

Three meanings of "loop" map to three mechanisms:
  1. "Run this node for every item." Default. Most nodes loop automatically, so do nothing.
  2. "Run this node once with all items, not once per item." The
    executeOnce
    setting (single boolean).
  3. "Process items in explicit batches with control flow between iterations." The
    Loop Over Items
    node (formerly
    Split In Batches
    ).
For paginated APIs, the HTTP Request node has built-in pagination. Almost always preferable to a hand-built page-counting loop.
“循环”的三种含义对应三种实现机制:
  1. 「为每个条目运行此节点。」 默认行为。大多数节点会自动循环,无需额外操作。
  2. 「一次性运行此节点,处理所有条目,而非逐条目运行。」 使用
    executeOnce
    设置(布尔值开关)。
  3. 「通过显式批处理处理条目,并在迭代间控制流程。」 使用
    Loop Over Items
    节点(原
    Split In Batches
    )。
对于分页API,HTTP Request节点内置分页功能。通常比手动构建的页数计数循环更优。

The model: items are an array

核心模型:条目以数组形式流动

Data flows between nodes as an array of items, each
{ json: {...}, binary?: {...} }
. 50 items = 50-entry array.
Default: a node runs once per item. An HTTP Request with 50 input items fires 50 requests and outputs 50 result items. This is the implicit loop most workflows rely on.
The input array is the loop. Control iteration by controlling the array.
数据在节点间以条目数组的形式传递,每个条目结构为
{ json: {...}, binary?: {...} }
。50个条目即对应50元素的数组。
默认行为:节点逐条目运行。一个带有50个输入条目的HTTP Request节点会发起50次请求,并输出50个结果条目。这是大多数工作流依赖的隐式循环。
输入数组即为循环的载体。通过控制数组来实现对迭代的控制。

Non-negotiable

必须遵守的规则

executeOnce: true
whenever a node should fire once-per-run, not once-per-item.
Includes any expression aggregating across the dataset via
$input.all()
/
$('Node').all()
plus
.map()
/
.filter()
/
.reduce()
(without it, the aggregate computes N times for N upstream items, often producing N duplicates downstream). Also includes single notifications, aggregate writes, summary messages.
Counter-case:
.all()
combined with another node's
.item
(a per-item lookup, e.g.,
$('Get Tags').all().filter(tag => $('Search Posts').item.json.tag_ids.includes(tag.json.id))
) is real per-item work and should keep
executeOnce
off. See the
n8n-expressions
skill's executeOnce section for the full distinction.
当节点需要每次工作流运行触发一次而非逐条目触发时,务必设置
executeOnce: true
。包括任何通过
$input.all()
/
$('Node').all()
结合
.map()
/
.filter()
/
.reduce()
聚合整个数据集的表达式(若不设置,聚合操作会针对上游N个条目执行N次,通常会在下游产生N个重复结果)。还包括单次通知、聚合写入、汇总消息等场景。
反例
.all()
结合另一个节点的
.item
(逐条目查找,例如
$('Get Tags').all().filter(tag => $('Search Posts').item.json.tag_ids.includes(tag.json.id))
)属于真正的逐条目操作,应保持
executeOnce
为关闭状态。详见
n8n-expressions
技能中的executeOnce章节以明确区分。

Strong defaults

推荐默认实践

  • Don't build a loop when default iteration suffices. Most nodes (HTTP Request, native service nodes, Set, IF/Switch) run once per input item automatically: N items in, N runs. To make N HTTP calls or create N records, just connect the source to the node. Don't reach for
    Loop Over Items
    unless you need per-iteration control. (Note:
    Execute Workflow
    is the exception. It defaults to a single all-items batch. See
    n8n-subworkflows
    for
    mode: 'each'
    .)
  • For paginated APIs, use HTTP Request's built-in pagination. Don't reinvent with
    Loop Over Items
    + manual
    $pageCount
    unless the API is genuinely odd. See
    references/HTTP_PAGINATION.md
    .
  • Loop Over Items
    is for explicit batching or per-iteration control
    (rate limiting, per-batch error recovery, stateful chunks, polling). See
    references/LOOP_OVER_ITEMS.md
    .
  • 当默认迭代足够时,不要手动构建循环。大多数节点(HTTP Request、原生服务节点、Set、IF/Switch)会自动逐输入条目运行:N个输入条目对应N次运行。要发起N次HTTP调用或创建N条记录,只需将源节点连接到目标节点即可。除非需要迭代间控制,否则不要使用
    Loop Over Items
    。(注意:
    Execute Workflow
    是例外。它默认以全条目批处理模式运行。详见
    n8n-subworkflows
    中的
    mode: 'each'
    设置。)
  • 对于分页API,使用HTTP Request的内置分页功能。除非API行为特殊,否则不要用
    Loop Over Items
    + 手动
    $pageCount
    来重复造轮子。详见
    references/HTTP_PAGINATION.md
  • Loop Over Items
    用于显式批处理或迭代间控制
    (限频、批处理错误恢复、有状态分块、轮询)。详见
    references/LOOP_OVER_ITEMS.md

Decision tree: which mechanism do I need?

决策树:选择合适的循环机制

Need to do something for each item?
├── Default per-item iteration is enough
│   └── Just connect the node. Done.
├── The node should run once total, not once per item?
│   └── Set executeOnce: true on the node
├── Paginated API (multiple HTTP calls to fetch all pages)?
│   └── Use HTTP Request's Pagination option (see references/HTTP_PAGINATION.md)
├── Need explicit batching (rate limit, chunk size, per-batch error handling)?
│   └── Use Loop Over Items node (see references/LOOP_OVER_ITEMS.md)
└── Need to recurse / repeat with state until a condition is met?
    └── Loop Over Items with Reset, OR a sub-workflow that calls itself.
        Both are advanced patterns; see references/LOOP_OVER_ITEMS.md.
需要为每个条目执行操作吗?
├── 默认逐条目迭代足够
│   └── 直接连接节点即可。完成。
├── 节点需总共运行一次,而非逐条目运行?
│   └── 在节点上设置executeOnce: true
├── 分页API(需多次HTTP调用获取所有页面)?
│   └── 使用HTTP Request的分页选项(详见references/HTTP_PAGINATION.md)
├── 需要显式批处理(限频、分块大小、批处理错误处理)?
│   └── 使用Loop Over Items节点(详见references/LOOP_OVER_ITEMS.md)
└── 需要递归/带状态重复直到满足条件?
    └── 使用带Reset的Loop Over Items,或调用自身的子工作流。
        两者均为高级模式;详见references/LOOP_OVER_ITEMS.md。

executeOnce
: the single-fire setting

executeOnce
:单次触发设置

Every node's Settings tab has an Execute Once toggle. When on, the node runs once using only the first input item.
ts
{
    name: 'Aggregate Slack',
    type: 'n8n-nodes-base.slack',
    parameters: { /* ... */ },
    executeOnce: true,
}
When to use it:
  • Notifications and aggregate writes. A "summary message" shouldn't fire 100 times because 100 items came in.
  • Counters, totals, reports. Anything computing
    $input.all().length
    etc. should run once.
  • Expressions aggregating across the full array via
    $input.all()
    /
    $('Node').all()
    .
    Otherwise the aggregate runs per upstream item. (Per-item lookups using
    .all()
    filtered by another node's
    .item
    are the counter-case, see
    n8n-expressions
    .)
When NOT to use it:
  • Per-item operations. One notification per item is the default and usually correct.
  • HTTP requests fanning out per item. You want one call per item.
Most common mistake: forgetting
executeOnce
on an aggregate node, then seeing the same message fire 50 times after a fan-out.
每个节点的设置选项卡都有一个Execute Once开关。开启后,节点仅使用第一个输入条目运行一次。
ts
{
    name: 'Aggregate Slack',
    type: 'n8n-nodes-base.slack',
    parameters: { /* ... */ },
    executeOnce: true,
}
适用场景:
  • 通知与聚合写入。「汇总消息」不应因传入100个条目而触发100次。
  • 计数器、总计、报表。任何计算
    $input.all().length
    等操作的节点应仅运行一次。
  • 通过
    $input.all()
    /
    $('Node').all()
    聚合整个数组的表达式
    。否则聚合操作会针对每个上游条目执行。(通过
    .all()
    结合另一个节点的
    .item
    进行的逐条目查找是反例,详见
    n8n-expressions
    。)
不适用场景:
  • 逐条目操作。为每个条目发送一条通知是默认行为,通常是正确的。
  • 逐条目发起HTTP请求。你需要为每个条目发起一次调用。
最常见错误:在聚合节点上忘记设置
executeOnce
,导致扇出后相同消息触发50次。

When the implicit loop bites you

隐式循环的常见问题

Default per-item iteration is great until it isn't. Common surprises:
默认逐条目迭代通常很好,但也会有意外情况:

A "single" config node fires per item

“单个”配置节点逐条目触发

A
Set
node after a fan-out runs once per item, producing N copies of the same constants. Usually fine, but expensive expressions (long
JSON.stringify
, Luxon parse) run N times. Move the Set above the fan-out, or set
executeOnce: true
.
扇出后的
Set
节点会逐条目运行,生成N个相同常量的副本。通常没问题,但耗时的表达式(如长
JSON.stringify
、Luxon解析)会执行N次。可将Set节点移至扇出之前,或设置
executeOnce: true

An aggregate Code node runs N times

聚合Code节点运行N次

A Code node reading
$input.all()
to compute a sum runs once per upstream item without
executeOnce: true
, producing N identical items. Set
executeOnce: true
.
读取
$input.all()
计算总和的Code节点,若未设置
executeOnce: true
,会针对每个上游条目运行一次,生成N个相同的条目。设置
executeOnce: true
即可解决。

A respond-to-webhook fires twice

响应Webhook触发两次

Most painful version. Respond-to-Webhook fires per input item, and two branches converging without a merge fire it twice: first response wins, the rest log errors. Merge first, or ensure only one branch reaches the responder. See
n8n-connections
FAN_OUT_FAN_IN.md
.
最棘手的情况。Respond-to-Webhook会逐输入条目触发,若两个分支未合并就到达响应节点,会触发两次:第一个响应生效,其余会记录错误。先合并分支,或确保只有一个分支到达响应节点。详见
n8n-connections
FAN_OUT_FAN_IN.md

An LLM call fires N times when you wanted one summary

LLM调用触发N次而非一次汇总

Same shape as the aggregate Code node. An LLM node with
$input.all()
in its prompt makes N identical calls, costs N tokens, returns N identical answers without
executeOnce: true
.
与聚合Code节点情况相同。提示中包含
$input.all()
的LLM节点,若未设置
executeOnce: true
,会发起N次相同调用,消耗N倍令牌,返回N个相同结果。

When to reach for
Loop Over Items

何时使用
Loop Over Items

Default iteration handles most cases. Use
Loop Over Items
for:
  • Rate limiting. "Process 10 at a time, 1s wait between batches."
  • Batched API calls with array bodies. "Send 50-item chunks to /bulk."
  • Per-batch error handling. "If a batch fails, log and continue."
  • Stateful iteration. "Each iteration depends on the previous output."
  • Polling a long-running job. "Start, check status every 30s until done or capped." Uses
    reset: true
    plus a
    $runIndex
    ceiling.
  • Per-item multi-branch with aggregation. "For each input, run transforms in parallel, merge, then aggregate." The done output (index 0) carries the result.
For wiring details, the output-index gotcha (output 0 = done, output 1 = loop), and worked examples, see
references/LOOP_OVER_ITEMS.md
.
默认迭代可处理大多数场景。在以下情况使用
Loop Over Items
  • 限频。「每次处理10个条目,批次间隔1秒。」
  • 带数组请求体的批处理API调用。「向/bulk发送50条目的分块。」
  • 批处理错误处理。「若批次失败,记录日志并继续。」
  • 有状态迭代。「每次迭代依赖前一次的输出。」
  • 轮询长时间运行的任务。「启动任务,每30秒检查状态,直到完成或达到上限。」需使用
    reset: true
    结合
    $runIndex
    上限。
  • 逐条目多分支聚合。「针对每个输入,并行运行转换操作,合并后再聚合。」完成输出(索引0)携带结果。
有关接线细节、输出索引陷阱(输出0 = 完成,输出1 = 循环)及示例,详见
references/LOOP_OVER_ITEMS.md

When NOT to reach for
Loop Over Items

何时不使用
Loop Over Items

The most common rationalization: "I need to wait for all items to finish before the next step, so I'll add Loop Over Items and use the
done
output." You don't need Loop Over Items for that. Default per-item iteration already waits: each item flows through the full downstream chain before the next item starts, and the post-loop node never fires "early."
The cure for that mistake is almost always: delete the Loop Over Items node, change nothing else, ship. That is Scenario 1 below, and it covers the majority of cases.
The four scenarios are independent. Read them as separate decisions, not as alternatives that all "replace" Loop Over Items. Most builds hit Scenario 1 and are done. Scenarios 2 and 3 only enter the picture when their specific goal applies. Scenario 4 is the narrow case where Loop Over Items actually earns its place.
最常见的错误理由:「我需要等所有条目处理完再进行下一步,所以添加Loop Over Items并使用
done
输出。」你不需要为此使用Loop Over Items。默认逐条目迭代已经会等待:每个条目会先走完下游完整流程,再处理下一个条目,循环后的节点绝不会「提前」触发。
解决此错误的方法几乎总是:删除Loop Over Items节点,其余保持不变,即可部署。这属于下文的场景1,覆盖大多数情况。
四个场景相互独立。将它们视为独立决策,而非替代Loop Over Items的方案。大多数构建会采用场景1即可完成。场景2和3仅在特定目标适用时才会用到。场景4是Loop Over Items真正适用的窄场景。

Scenario 1: default per-item iteration (the default, most common)

场景1:默认逐条目迭代(默认,最常见)

Source emits N items, per-item processor runs N times, downstream chain follows. No Loop Over Items, no
executeOnce
, no Aggregate.
Just connect the nodes.
[Source: 20 items]
  → [Per-item processor]   # default iter, runs 20 times
  → [Next step]            # runs after each item, in order
If a
Loop Over Items + done
was added here "to wait for all items" or "to make the next node run for each item," delete the Loop Over Items node and wire source straight to processor. Do not replace it with anything. Default iteration already does the job. The exception is
Execute Workflow
(sub-workflow): it defaults to a single all-items batch, so per-item invocation needs
mode: 'each'
on that node, not a Loop. See
n8n-subworkflows
.
源节点输出N个条目,逐条目处理器运行N次,下游流程跟进。无需Loop Over Items、无需
executeOnce
、无需聚合
。只需连接节点即可。
[源节点:20个条目]
  → [逐条目处理器]   # 默认迭代,运行20次
  → [下一步]            # 每个条目处理完后触发,按顺序执行
如果此处添加
Loop Over Items + done
是为了「等待所有条目完成」或「让下一个节点逐条目运行」,请删除Loop Over Items节点,将源节点直接连接到处理器。无需替换为任何其他节点。默认迭代已完成该工作。例外情况是
Execute Workflow
(子工作流):它默认以全条目批处理模式运行,因此逐条目调用需在该节点上设置
mode: 'each'
,而非使用循环。详见
n8n-subworkflows

Scenario 2: a downstream node should fire once total (
executeOnce: true
)

场景2:下游节点需总共触发一次(
executeOnce: true

Independent of Scenario 1. Triggered only when there is a SPECIFIC downstream node whose job is once-per-run, not once-per-item: one digest email after 20 papers process, one summary write after the loop, one final Slack notification.
Set
executeOnce: true
on that node. The node receives all upstream items but runs once. This is a per-node setting, not a Loop replacement: the per-item processor in Scenario 1 still runs N times, and only this one downstream node collapses.
独立于场景1。仅当存在特定下游节点需要每次工作流运行触发一次而非逐条目触发时才使用:20篇文档处理完成后发送一封摘要邮件,循环结束后进行一次汇总写入,发送最后一条Slack通知。
在该节点上设置
executeOnce: true
。节点会接收所有上游条目,但仅运行一次。这是节点级设置,而非循环替代方案:场景1中的逐条目处理器仍会运行N次,仅该下游节点会合并为单次运行。

Scenario 3: a node needs the items as a single array (Aggregate)

场景3:节点需要条目作为单个数组(聚合)

Independent of Scenario 1. Triggered only when a downstream node's input contract is a list, not per-item invocations (e.g., a node taking a JSON array body, an LLM prompt that needs the whole list).
Use the Aggregate node to collapse the per-item stream into one item containing the array. Again, not a Loop replacement.
独立于场景1。仅当下游节点的输入要求为列表而非逐条目调用时才使用(例如,接收JSON数组请求体的节点,需要完整列表的LLM提示)。
使用Aggregate节点将逐条目流合并为包含数组的单个条目。同样,这不是循环替代方案。

Scenario 4: genuine batching (the only time Loop Over Items earns its place)

场景4:真正的批处理(Loop Over Items唯一适用的场景)

Rate limiting (process N at a time with a Wait between batches), chunked bulk API calls (POST 50-item arrays to
/bulk
), per-batch error handling, polling a long-running job with
reset: true
and a
$runIndex
ceiling, stateful iteration where each batch depends on the previous output.
"Wait for items to finish" does not qualify. Default iteration already does that.
限频(每次处理N个条目,批次间等待)、分块批量API调用(向/bulk POST 50条目的数组)、批处理错误处理、使用
reset: true
$runIndex
上限轮询长时间运行的任务、每次批次依赖前一次输出的有状态迭代。
「等待条目完成」不属于此场景。默认迭代已完成该工作。

Quick disambiguation

快速区分

If your only reason for the Loop is "wait for items / run for each item," you are in Scenario 1. Delete the Loop. Do not add
executeOnce
or Aggregate as a substitute. They solve different problems and are only added when their own scenario applies.
如果使用循环的唯一理由是「等待条目完成/逐条目运行」,则属于场景1。删除循环。不要用
executeOnce
或聚合替代。它们解决的是不同问题,仅在各自场景适用时才添加。

When to reach for HTTP pagination

何时使用HTTP分页

Three common page shapes:
  • Next-URL in response. Each response includes a
    next
    link.
  • Page number/cursor parameter. Bump
    ?page=N
    or
    ?cursor=...
    each call.
  • Stop on empty page or specific status.
HTTP Request handles all natively via its Pagination option: set the mode, give a next-page expression, and the node loops internally, returning a single output array of all pages' items.
Don't reinvent with
Loop Over Items
+ manual
$pageCount
unless the API does something the built-in modes can't express.
See
references/HTTP_PAGINATION.md
.
三种常见的页面形式:
  • 响应中包含Next-URL。每个响应包含一个
    next
    链接。
  • 页码/游标参数。每次调用递增
    ?page=N
    ?cursor=...
  • 空页面或特定状态时停止
HTTP Request节点通过其Pagination选项原生支持所有这些形式:设置模式,提供下一页表达式,节点会在内部循环,返回包含所有页面条目的单个输出数组。
除非API行为特殊到内置模式无法表达,否则不要用
Loop Over Items
+ 手动
$pageCount
重复造轮子。详见
references/HTTP_PAGINATION.md

Sub-workflow recursion

子工作流递归

For genuinely recursive work (tree walking, retry-with-backoff, "process this and its children"), a self-calling sub-workflow is cleaner than
Loop Over Items
with
Reset
. Input parameters carry recursion state.
Sub-workflow: Walk Tree
  inputs: { node_id, depth }
  body: process node, look up children, for each child call self with depth+1
Watch recursion depth. n8n has nested-execution limits. For deep recursion, a queue + flat loop beats true recursion.
对于真正的递归工作(遍历树、退避重试、「处理此条目及其子条目」),调用自身的子工作流比带
Reset
Loop Over Items
更简洁。输入参数携带递归状态。
子工作流:遍历树
  输入:{ node_id, depth }
  主体:处理节点,查找子节点,为每个子节点调用自身并传入depth+1
注意递归深度。n8n有嵌套执行限制。对于深度递归,队列+扁平循环优于真正的递归。

Reference files

参考文件

FileRead when
references/LOOP_OVER_ITEMS.md
Configuring the Loop Over Items node, batching, rate limiting, stateful iteration
references/HTTP_PAGINATION.md
Calling a paginated API, configuring HTTP Request pagination modes
文件阅读场景
references/LOOP_OVER_ITEMS.md
配置Loop Over Items节点、批处理、限频、有状态迭代
references/HTTP_PAGINATION.md
调用分页API、配置HTTP Request分页模式

Anti-patterns

反模式

Anti-patternWhat goes wrongFix
Adding
Loop Over Items
to "make it loop" when default iteration already does
Workflow harder to read for no benefit, and loop output vs done output gets miswiredJust connect the node directly and let default iteration handle it
Aggregate Code node without
executeOnce
Same aggregate computed N times, output has N identical itemsSet
executeOnce: true
Manual pagination loop with
Loop Over Items
+
$pageCount
Reinvents what HTTP Request does natively, with brittle stop conditionsUse HTTP Request's
Pagination
option
Sending one Slack message per item when you wanted a summarySlack channel floods, rate limits hit, embarrassment
executeOnce: true
on the Slack node, build the summary upstream
Two branches both reach
Respond to Webhook
Responds twice, downstream callers see errorsMerge before the responder, or ensure only one branch reaches it
Loop Over Items
with
Reset
and no clear termination
Infinite loop, n8n eats memory until the execution is killedAlways have a clear termination condition. Prefer HTTP pagination for paged APIs
Nesting one
Loop Over Items
inside another in the same workflow
Broken at runtime, validation passesMove the inner loop into a sub-workflow called per outer iteration. See
n8n-subworkflows
mode: 'each'
反模式问题修复方案
当默认迭代已实现循环时,仍添加
Loop Over Items
「实现循环」
工作流可读性降低且无收益,还可能误接循环输出与完成输出直接连接节点,让默认迭代处理
聚合Code节点未设置
executeOnce
相同聚合操作执行N次,输出包含N个相同条目设置
executeOnce: true
使用
Loop Over Items
+
$pageCount
手动实现分页循环
重复造HTTP Request原生支持的功能,终止条件脆弱使用HTTP Request的
Pagination
选项
逐条目发送Slack消息而非汇总消息Slack频道被刷屏,触发限频,造成困扰在Slack节点上设置
executeOnce: true
,提前构建汇总内容
两个分支均到达
Respond to Webhook
响应两次,下游调用方看到错误在响应节点前合并分支,或确保只有一个分支到达响应节点
Loop Over Items
设置
Reset
但无明确终止条件
无限循环,n8n占用内存直到执行被终止始终设置明确的终止条件。分页API优先使用HTTP分页
在同一工作流中嵌套
Loop Over Items
运行时出错,但验证通过将内层循环移至子工作流,在外层迭代时调用该子工作流。详见
n8n-subworkflows
mode: 'each'