
n8n-code-javascript
热门在 n8n Code 节点中编写 JavaScript 代码。当你在 n8n 中使用 JavaScript、使用 $input/$json/$node 语法、通过 this.helpers / $helpers 全局对象发起 HTTP 请求、使用 DateTime 处理日期、排查 Code 节点错误、选择 Code 节点模式,或进行任何自定义数据转换时,请使用此技能。当工作流需要 Code 节点时——无论是数据聚合、过滤、API 调用、格式转换、批处理逻辑还是任何自定义 JavaScript——始终使用此技能。涵盖 SplitInBatches 循环模式、跨迭代数据、pairedItem 以及实际生产模式。当被问及为什么 Code 节点或工作流运行缓慢、哪种执行模式更快、或如何减少大数据集上的每项开销时,也请使用此技能。例外情况——对于 AI 代理可调用的自定义代码工具(@n8n/n8n-nodes-langchain.toolCode,附加到 AI 代理的工具),请改用 n8n-code-tool 技能;它具有不同的运行时契约。
Write JavaScript code in n8n Code nodes. Use when writing JavaScript in n8n, using $input/$json/$node syntax, making HTTP requests with this.helpers / the $helpers global, working with dates using DateTime, troubleshooting Code node errors, choosing between Code node modes, or doing any custom data transformation in n8n. Always use this skill when a workflow needs a Code node — whether for data aggregation, filtering, API calls, format conversion, batch processing logic, or any custom JavaScript. Covers SplitInBatches loop patterns, cross-iteration data, pairedItem, and real-world production patterns. Also use when asked why a Code node or workflow is slow, which execution mode is faster, or how to cut per-item overhead on large datasets. EXCEPTION — for the AI-agent-callable Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode, a tool attached to an AI Agent), use the n8n-code-tool skill instead; it has a different runtime contract.
JavaScript Code 节点
在 n8n Code 节点中编写 JavaScript 代码的专家指南。
快速开始
// Code 节点的基本模板
const items = $input.all();
// 处理数据
const processed = items.map(item => ({
json: {
...item.json,
processed: true,
timestamp: new Date().toISOString()
}
}));
return processed;
基本规则
- 选择“Run Once for All Items”模式(推荐用于大多数用例)
- 访问数据:
$input.all()、$input.first()或$input.item - 返回
[{json: {...}}]——这是规范且模式可移植的形式。在“Run Once for All Items”模式下,n8n 也会自动包装裸的return {…}对象,因此也能运行;真正失败的是返回原始类型(字符串/数字)或null。 - 关键:Webhook 数据位于
$json.body下(而不是直接$json) - 可用的内置功能:
this.helpers.httpRequest()(无认证——裸的$helpers全局对象在任务运行器沙箱中为 undefined,因此$helpers.httpRequest()会抛出ReferenceError: $helpers is not defined)、DateTime(Luxon)、$jmespath()。不可用:this.helpers.httpRequestWithAuthentication(被拒绝列表)、$env(当 N8N_BLOCK_ENV_ACCESS_IN_NODE=true 时)、require()(除非在白名单中)。对于超出简单未认证 GET 请求(认证、分页、重试)的情况,优先使用 HTTP Request 节点,并将 Code 节点用于纯逻辑。 - 实例白名单库:自托管实例可以通过
N8N_RUNNERS_ALLOWED_BUILT_IN_MODULES和N8N_RUNNERS_ALLOWED_EXTERNAL_MODULES(旧版:NODE_FUNCTION_ALLOW_BUILTIN/NODE_FUNCTION_ALLOW_EXTERNAL)将模块加入白名单。如果用户说其实例允许特定模块(例如axios、lodash、crypto),则通过require()使用它们——不要拒绝。如果不确定,请询问或默认仅使用内置模块。 - 错误的技能? 如果你正在为附加到 AI 代理的 Custom Code Tool(
@n8n/n8n-nodes-langchain.toolCode)编写代码,请停止——该节点有不同的契约(通过query输入,必须返回字符串,没有$input/$helpers)。请使用 n8n-code-tool 技能。
模式选择指南
Code 节点提供两种执行模式。根据你的用例选择:
Run Once for All Items(推荐 - 默认)
此模式用于: 95% 的用例
- 工作原理:无论输入数量多少,代码执行 一次
- 数据访问:
$input.all()或items数组 - 最适合:聚合、过滤、批处理、转换、使用所有数据进行 API 调用
- 性能:对于多个项目更快(单次执行)
// 示例:计算所有项目的总和
const allItems = $input.all();
const total = allItems.reduce((sum, item) => sum + (item.json.amount || 0), 0);
return [{
json: {
total,
count: allItems.length,
average: total / allItems.length
}
}];
何时使用:
- ✅ 比较数据集中的项目
- ✅ 计算总计、平均值或统计信息
- ✅ 排序或排名项目
- ✅ 去重
- ✅ 构建聚合报告
- ✅ 合并多个项目的数据
Run Once for Each Item
此模式用于: 仅限特殊情况
- 工作原理:代码为每个输入项目 单独 执行
- 数据访问:
$input.item或$item - 最适合:特定于项目的逻辑、独立操作、每个项目的验证
- 性能:对于大数据集较慢(多次执行)
// 示例:为每个项目添加处理时间戳
const item = $input.item;
return [{
json: {
...item.json,
processed: true,
processedAt: new Date().toISOString()
}
}];
何时使用:
- ✅ 每个项目需要独立的 API 调用
- ✅ 每个项目验证,具有不同的错误处理
- ✅ 基于项目属性的特定转换
- ✅ 当项目必须单独处理以满足业务逻辑时
决策捷径:
- 需要查看多个项目? → 使用“All Items”模式
- 每个项目完全独立? → 使用“Each Item”模式
- 不确定? → 使用“All Items”模式(你始终可以在内部循环)
为什么“All Items”更快——每项边界
模式选择是 Code 节点中最大的性能杠杆。每个 per-item 执行上下文都会产生设置开销(在 n8n 2.x 上测量,小记录):
| 每项运行什么 | 大致成本 |
|---|---|
| Code All Items(整个集合运行一次) | ~0.02 ms/项 |
| 任何节点中的表达式(IF / Set 等) | ~0.2 ms/项 |
| Code Each Item(每个项目一个完整沙箱) | ~0.6 ms/项——比 All Items 慢约 25–30 倍 |
因此,对 10k 个项目使用 Run Once for Each Item 会产生约 6 秒的纯开销,而 Run Once for All Items 仅约 0.2 秒。仅当项目确实需要隔离(独立的错误处理,或无法批处理的每项 API 调用)时才使用 Each Item;否则,在一个 All Items 节点内部循环。表达式复杂性本身基本上是免费的(约 90% 的成本来自每项上下文,而不是你的代码),并且每个节点→节点的跳转会重新复制所有项目——因此减少 per-item 边界的数量,而不是微优化每个边界。在几百个项目以下,这些都不重要;在热路径上(大量项目,少量 I/O)才需要考虑。
参见:DATA_ACCESS.md → “Mode Performance” 了解推论、跳转成本和规模检查。
数据访问模式
从上游节点获取数据的四种方式。注意 $node["Name"] 和 $('Name') 需要 .first().json 或 .all()——永远不要直接使用 .json。
const allItems = $input.all(); // 1. 所有项目——批量操作、聚合(最常见)
const data = $input.first().json; // 2. 第一个项目——单个对象、API 响应
const item = $input.item; // 3. 当前项目——仅“Each Item”模式(否则为 undefined)
const other = $node["Webhook"].json; // 4. 命名节点——跨节点合并数据
始终通过 .json 访问字段(例如 item.json.name,而不是 item.name),并优先使用显式的 $input.first().json.field 而不是裸的 $json.field。
参见:DATA_ACCESS.md 获取完整指南——每个模式都有示例、决策树和常见错误(修改原始数据、缺少长度检查、在错误模式下使用 $input.item)。
关键:Webhook 数据结构
最常见的错误:Webhook 数据嵌套在 .body 下
// ❌ 错误 - 将返回 undefined
const name = $json.name;
const email = $json.email;
// ✅ 正确 - Webhook 数据在 .body 下
const name = $json.body.name;
const email = $json.body.email;
// 或者使用 $input
const webhookData = $input.first().json.body;
const name = webhookData.name;
原因:Webhook 节点将所有请求数据包装在 body 属性下。这包括 POST 数据、查询参数和 JSON 负载。
参见:DATA_ACCESS.md 获取完整的 webhook 结构详情
返回格式要求
规范形式:[{json: {...}}]——一个对象数组,每个对象都有一个 json 属性。它在两种执行模式下都明确且工作方式相同,因此请将其设为默认。
在“Run Once for All Items”模式下,n8n 会自动规范化输出中的松散形状:单个裸对象或裸对象数组会被自动包装在 json 下。因此 return {foo: 1} 可以运行。没有东西可包装——因此真正在运行时失败并显示“Code doesn't return items properly”——的是原始类型(字符串/数字/布尔值)或 null/undefined。(n8n-mcp ≥ 2.63.0 不再将裸对象返回标记为错误;它反映了这种自动包装行为。)
正确的返回格式
// ✅ 单个结果
return [{
json: {
field1: value1,
field2: value2
}
}];
// ✅ 多个结果
return [
{json: {id: 1, data: 'first'}},
{json: {id: 2, data: 'second'}}
];
// ✅ 转换后的数组
const transformed = $input.all()
.filter(item => item.json.valid)
.map(item => ({
json: {
id: item.json.id,
processed: true
}
}));
return transformed;
// ✅ 空结果(当没有数据返回时)
return [];
// ✅ 条件返回
if (shouldProcess) {
return [{json: processedData}];
} else {
return [];
}
非规范返回(自动包装——优先使用规范形式)
// ⚠️ 在 All Items 模式下自动包装 → [{json: {field: value}}]。可以运行,但优先使用数组形式。
return {
json: {field: value}
};
// ⚠️ 自动包装 → [{json: {field: value}}]。可以运行,但添加 json 包装器以保持清晰。
return [{field: value}];
// ✅ 没问题——输入项目已经带有 json 属性,因此原样返回是有效的直通
return $input.all();
真正错误的返回
// ❌ 失败:原始类型——n8n 报错“Code doesn't return items properly”
return "processed";
// ❌ 失败:null / undefined——没有东西传递给下一个节点
return null;
为什么重要:规范的 [{json: {...}}] 是明确的,并且在两种模式下行为相同。n8n 在 All Items 模式下会自动规范化裸对象和对象数组,但原始类型或 null 返回没有东西可包装,会停止执行。
参见:ERROR_PATTERNS.md #3 获取详细的错误解决方案
常见模式概述
来自生产工作流的最有用的 Code 节点形状。一个快速示例——对所有项目求和/聚合:
const items = $input.all();
const total = items.reduce((sum, item) => sum + (item.json.amount || 0), 0);
return [{ json: { total, count: items.length, average: total / items.length } }];
完整库涵盖 10 种模式:多源聚合、正则表达式过滤、Markdown/结构化文本解析、JSON 比较、CRM/表单转换、发布处理、带计算字段的数组转换、Slack Block Kit 格式化、Top-N 排名和字符串聚合报告——每种都有变体。
参见:COMMON_PATTERNS.md 获取 10 个详细的生产模式(以及最佳实践部分:验证输入、try-catch、尽早过滤、数组方法优于循环、console.log 调试)。
错误预防 - 最常见的错误
反复出现的 Code 节点失败,按大致频率排序:
- 空代码 / 缺少 return——始终以
return [...]结束,并确保 每个 分支都返回。 - 将表达式语法当作代码——不要在 JavaScript 所在的位置写
{{ }}(return {{ $json.x }}是语法错误)。使用`${$json.field}`或$input.first().json.field。{{ }}在字符串字面量内部 是可以的——它只是 n8n 不会评估的文本。 - 返回形状——优先使用
return [{json:{...}}]。裸的return {…}在 All Items 模式下会自动包装,但返回原始类型(字符串/数字)或null才是真正失败的。 - 缺少空值检查——使用可选链:
item.json?.user?.email || 'fallback'。 - Webhook body 嵌套——
$json.email是 undefined;使用$json.body.email。 - 认证助手被阻止(
httpRequestWithAuthentication)和$env被阻止——通过凭据/HTTP Request 节点路由秘密,而不是 Code 节点沙箱。
参见:ERROR_PATTERNS.md 获取全面指南——每个错误都有错误/正确代码、转义规则、沙箱限制(错误 #6–#7)、预防清单和快速错误消息查找表。
内置函数和助手
// HTTP 请求(无认证——参见下面的沙箱说明)
const res = await this.helpers.httpRequest({ method: 'GET', url: 'https://api.example.com/data' });
// DateTime (Luxon):当前时间、格式化、算术
const now = DateTime.now();
const formatted = now.toFormat('yyyy-MM-dd');
const tomorrow = now.plus({ days: 1 });
// $jmespath()——查询 JSON 结构
const adults = $jmespath($input.first().json, 'users[?age >= `18`]');
// $getWorkflowStaticData()——跨执行持久化的数据
沙箱(自 n8n v2.0 起,JsTaskRunnerSandbox): 访问器是 this.helpers.httpRequest()——裸的 $helpers 全局对象在此处为 undefined($helpers.httpRequest() 会抛出 ReferenceError)。在嵌套的异步函数中,this 会丢失,请将其作为 await fn.call(this, ...) 调用。this.helpers.httpRequestWithAuthentication 和 this.helpers.requestWithAuthenticationPaginated 被拒绝列表(→ UnsupportedFunctionError);对于认证调用,请使用带有凭据的 HTTP Request 节点(首选)、子工作流,或仅在令牌已作为数据流经工作流时,在 this.helpers.httpRequest() 上手动添加 Authorization: Bearer ${token} 标头。当 N8N_BLOCK_ENV_ACCESS_IN_NODE=true 时,$env 被阻止;require() 仅适用于白名单模块。Buffer、URL 和标准 JS 全局对象(Math、JSON、Object、Array)始终有效。
参见:BUILTIN_FUNCTIONS.md 获取完整参考——完整的 httpRequest 选项、所有 DateTime/Luxon 操作、JMESPath 模式、静态数据用例和沙箱限制详情。
最佳实践
- 首先验证输入——在处理之前检查空数组 / 缺少
.json。 - 对风险工作使用 try-catch(HTTP 调用)并返回错误对象而不是崩溃。
- 优先使用数组方法(
filter/map/reduce)而不是手动循环。 - 尽早过滤,稍后转换——在执行昂贵工作之前缩小数据集。
- 描述性名称和
console.log()用于调试(输出到浏览器控制台)。
参见:COMMON_PATTERNS.md → “Best Practices” 获取每个的代码示例。
生产陷阱
来自实际部署的来之不易的经验——总结如下,代码在 DATA_ACCESS.md → “Production Gotchas”:
- SplitInBatches 输出违反直觉:
main[0]= 完成(触发一次,在所有批次之后),main[1]= 每个批次(循环体)。在完成输出后添加一个 Limit 1 节点作为安全措施。 - 迭代次数就是成本:每次循环迭代都会通过引擎重新运行整个主体(每次约 0.8 ms 开销)。
batchSize: 1相当于 Each Item 的循环版本——使用你的实际约束(速率限制、页面大小、内存)允许的最大批次,或者根本不循环。 - 跨迭代累积(关键):循环后,
$('Node Inside Loop').all()仅返回最后一次迭代的项目。通过$getWorkflowStaticData('global')累积(之前重置,内部推送,之后读取)。 - pairedItem:当发出的项目与输入不是 1:1 映射时,设置
pairedItem: { item: i },否则下游 Set 节点会失败并显示paired_item_no_info。 - 节点引用语法:
$('Node').first().json或$('Node').all()——永远不要直接在引用上使用.json。 - 浮点精度:在分级别比较货币——
Math.round(a*100) !== Math.round(b*100)——以避免浮点噪声导致的误报。
何时使用 Code 节点
在求助于 Code 节点之前,请先通过 n8n Expression Syntax 技能中的转换守门人:表达式 → Edit Fields 字段中的箭头函数 IIFE → Code 节点,按此顺序。前两条路径涵盖大多数“转换此数据”任务,每个约 1–10ms,而 Code 节点的沙箱化约 500–1000ms——在纯单项目塑造上约有 100 倍的差距,且功能上没有区别。Code 节点仅在需要整个数据集聚合(
$input.all())、白名单库或异步工作时才值得使用。在编写用于加密(HMAC、哈希、签名)或 XML/SOAP/RSS 解析的代码之前,请检查是否有 原生节点——n8n 有一个 Crypto 节点(nodes-base.crypto)和一个 XML 节点(nodes-base.xml),它们无需任何 JavaScript 即可完成这些工作。为原生节点已经完成的事情而使用 Code 节点是最常见的误报之一。
在以下情况下使用 Code 节点:
- ✅ 需要多个步骤的复杂转换
- ✅ 自定义计算或业务逻辑
- ✅ 递归操作
- ✅ 具有复杂结构的 API 响应解析
- ✅ 多步骤条件判断
- ✅ 跨项目的数据聚合
在以下情况下考虑其他节点:
- ❌ 简单字段映射 → 使用 Set 节点
- ❌ 基本过滤 → 使用 Filter 节点
- ❌ 简单条件判断 → 使用 IF 或 Switch 节点
- ❌ 仅 HTTP 请求 → 使用 HTTP Request 节点
Code 节点擅长:需要链接多个简单节点的复杂逻辑
与其他技能的集成
配合使用:
n8n Expression Syntax:
- 表达式在其他节点中使用
{{ }}语法 - Code 节点直接使用 JavaScript(无
{{ }}) - 何时使用表达式 vs 代码
n8n MCP Tools Expert:
- 如何查找 Code 节点:
search_nodes({query: "code"}) - 获取配置帮助:
get_node({nodeType: "nodes-base.code"}) - 验证代码:
validate_node({nodeType: "nodes-base.code", config: {...}})
n8n Node Configuration:
- 模式选择(All Items vs Each Item)
- 语言选择(JavaScript vs Python)
- 理解属性依赖
n8n Workflow Patterns:
- 转换步骤中的 Code 节点
- Webhook → Code → API 模式
- 工作流中的错误处理
n8n Validation Expert:
- 验证 Code 节点配置
- 处理验证错误
- 自动修复常见问题
快速参考清单
在部署 Code 节点之前,请验证:
- [ ] 代码不为空 - 必须有有意义的逻辑
- [ ] 存在 return 语句 - 返回项目,而不是原始类型/
null - [ ] 规范返回格式 - 每个项目:
{json: {...}}(裸对象会自动包装,但请显式指定) - [ ] 数据访问正确 - 使用
$input.all()、$input.first()或$input.item - [ ] 没有将
{{ }}写为代码 - 使用 JavaScript 模板字面量:`${value}` - [ ] 错误处理 - 对 null/undefined 输入使用保护子句
- [ ] Webhook 数据 - 如果来自 webhook,通过
.body访问 - [ ] 模式选择 - 大多数情况下使用“All Items”
- [ ] 性能 - 优先使用 map/filter 而不是手动循环
- [ ] 输出一致 - 所有代码路径返回相同的结构
其他资源
相关文件
- DATA_ACCESS.md - 全面的数据访问模式
- COMMON_PATTERNS.md - 10 个经过生产测试的模式
- ERROR_PATTERNS.md - 前 5 个错误及解决方案
- BUILTIN_FUNCTIONS.md - 完整的内置函数参考
n8n 文档
- Code 节点指南:https://docs.n8n.io/code/code-node/
- 内置方法:https://docs.n8n.io/code-examples/methods-variables-reference/
- Luxon 文档:https://moment.github.io/luxon/
准备好编写 n8n Code 节点的 JavaScript 代码了! 从简单的转换开始,使用错误模式指南避免常见错误,并参考模式库获取生产就绪的示例。





