关于 n8n-code-javascript
为 n8n Code 节点编写 JavaScript 的指导技能,面向工作流构建者,涵盖执行模式、数据访问、返回格式及常见沙箱问题。
主要功能
- 01选择批量或逐项执行模式
- 02读取输入与 Webhook 数据
- 03返回有效的 n8n 数据项
- 04JavaScript 数据转换模式
- 05沙箱辅助方法与模块说明
适用场景
- 01汇总或筛选工作流数据项
- 02在 Code 节点转换数据
- 03排查返回格式错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ czlonkowski/ n8n-mcp --skill n8n-code-javascript安装后在 Claude Code 中输入/n8n-code-javascript确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
BUILTIN_FUNCTIONS.mdCOMMON_PATTERNS.mdDATA_ACCESS.mdERROR_PATTERNS.mdREADME.md详细介绍
JavaScript 代码节点
在 n8n Code 节点中编写 JavaScript 代码的专家指南。
快速入门
// Basic template for Code nodes
const items = $input.all();
// Process data
const processed = items.map(item => ({
json: {
...item.json,
processed: true,
timestamp: new Date().toISOString()
}
}));
return processed;
基本规则
- 选择“对所有项目运行一次”模式(适用于大多数用例)
- 访问数据:
$input.all()、$input.first()或$input.item - 返回
[{json: {...}}]——这是规范且兼容不同模式的形式。在对所有项目运行一次模式下,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 Agent 的 Custom Code Tool(
@n8n/n8n-nodes-langchain.toolCode)编写代码,请停下——该节点使用不同的契约(通过query输入,必须返回字符串,没有$input/$helpers)。请使用 n8n-code-tool 技能。
模式选择指南
Code 节点提供两种执行模式。请根据用例进行选择:
对所有项目运行一次(推荐 - 默认)
适用于: 95% 的用例
- 工作方式:无论输入数量多少,代码都只执行一次
- 数据访问:
$input.all()或items数组 - 最适用于:聚合、筛选、批处理、转换,以及使用所有数据进行 API 调用
- 性能:处理多个项目时更快(只执行一次)
// Example: Calculate total from all items
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
}
}];
适用场景:
- ✅ 跨数据集比较项目
- ✅ 计算总和、平均值或统计数据
- ✅ 对项目排序或排名
- ✅ 去重
- ✅ 生成汇总报告
- ✅ 合并多个项目中的数据
对每个项目运行一次
适用于: 仅限特殊情况
- 工作方式:针对每个输入项目分别执行代码
- 数据访问:
$input.item或$item - 最适用于:针对单个项目的逻辑、独立操作、逐项验证
- 性能:处理大型数据集时较慢(需多次执行)
// Example: Add processing timestamp to each item
const item = $input.item;
return [{
json: {
...item.json,
processed: true,
processedAt: new Date().toISOString()
}
}];
适用场景:
- ✅ 每个项目都需要独立的 API 调用
- ✅ 针对每个项目进行验证,并采用不同的错误处理方式
- ✅ 根据项目属性进行针对性转换
- ✅ 业务逻辑要求分别处理各个项目
快速决策:
- 需要查看多个项目? → 使用“所有项目”模式
- 每个项目都完全独立? → 使用“每个项目”模式
- 不确定? → 使用“所有项目”模式(你随时可以在内部循环)
为什么“All Items”更快——逐项边界
在 Code 节点中,模式选择是影响性能的最大因素。每个逐项执行上下文都会产生设置开销(在 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 s,而 Run Once for All Items 约为 ~0.2 s。只有在确实需要隔离单个项时才使用 Each Item(例如独立的错误处理,或无法批处理的逐项 API 调用);否则,应在一个 All Items 节点内部循环。表达式本身的复杂度几乎没有开销(约 90% 的成本来自逐项上下文,而不是代码),且每次节点之间的跳转都会重新复制所有项——因此要减少逐项边界的数量,而不是对每个边界做微优化。项数少于几百时,这些都无关紧要;只有在热路径上(项数多、I/O 少)才需要关注。
参见:DATA_ACCESS.md → “Mode Performance”,了解推论、跳转开销和规模检查。
数据访问模式
从上游节点获取数据的四种方式。请注意,$node["Name"] 和 $('Name') 需要使用 .first().json 或 .all()——不能直接使用 .json。
const allItems = $input.all(); // 1. All items — batch ops, aggregation (most common)
const data = $input.first().json; // 2. First item — single objects, API responses
const item = $input.item; // 3. Current item — "Each Item" mode ONLY (undefined otherwise)
const other = $node["Webhook"].json; // 4. Named node — combine data across nodes
始终通过 .json 访问字段(例如 item.json.name,而不是 item.name),并优先使用明确的 $input.first().json.field,而不是直接使用 $json.field。
参见:DATA_ACCESS.md,查看完整指南——包含每种模式的示例、决策树和常见错误(修改原始数据、缺少长度检查、在错误的模式中使用 $input.item)。
关键:Webhook 数据结构
最常见的错误:Webhook 数据嵌套在 .body 下
// ❌ WRONG - Will return undefined
const name = $json.name;
const email = $json.email;
// ✅ CORRECT - Webhook data is under .body
const name = $json.body.name;
const email = $json.body.email;
// Or with $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 不再将裸对象返回标记为错误,因为这反映了自动封装行为。)
正确的返回格式
// ✅ Single result
return [{
json: {
field1: value1,
field2: value2
}
}];
// ✅ Multiple results
return [
{json: {id: 1, data: 'first'}},
{json: {id: 2, data: 'second'}}
];
// ✅ Transformed array
const transformed = $input.all()
.filter(item => item.json.valid)
.map(item => ({
json: {
id: item.json.id,
processed: true
}
}));
return transformed;
// ✅ Empty result (when no data to return)
return [];
// ✅ Conditional return
if (shouldProcess) {
return [{json: processedData}];
} else {
return [];
}
非规范返回值(会自动封装——建议使用规范形式)
// ⚠️ Auto-wrapped in All Items mode → [{json: {field: value}}]. Runs, but prefer the array form.
return {
json: {field: value}
};
// ⚠️ Auto-wrapped → [{json: {field: value}}]. Runs, but add the json wrapper for clarity.
return [{field: value}];
// ✅ Fine — input items already carry a json property, so returning them unchanged is a valid passthrough
return $input.all();
确实有问题的返回值
// ❌ FAILS: primitive — n8n errors "Code doesn't return items properly"
return "processed";
// ❌ FAILS: null / undefined — nothing to pass to the next node
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 格式化、前 N 项排名,以及字符串聚合报告——每种模式都包含不同变体。
参见:COMMON_PATTERNS.md,查看 10 种详细的生产模式(以及最佳实践章节:验证输入、try-catch、尽早筛选、优先使用数组方法而非循环、使用 console.log 调试)。
错误预防——常见错误
Code 节点反复出现的故障,按大致发生频率排序:
- 代码为空/缺少返回值——始终以
return [...]结束,并确保每个分支都有返回值。 - 把表达式语法当作代码——JavaScript 代码中不要写
{{ }}(return {{ $json.x }}会导致语法错误)。请使用`${$json.field}`或$input.first().json.field。在字符串字面量内部使用{{ }}没问题——它只是 n8n 不会求值的字面文本。 - 返回值形状——优先使用
return [{json:{...}}]。在 All Items 模式下,裸写return {…}会自动包装,但返回基本类型(字符串/数字)或null才会真正导致失败。 - 缺少 null 检查——使用可选链:
item.json?.user?.email || 'fallback'。 - Webhook 请求体嵌套——
$json.email未定义;请使用$json.body.email。 - 身份验证辅助函数被禁用(
httpRequestWithAuthentication),且$env被禁用——请通过凭据/HTTP Request 节点处理密钥,而不是在 Code 节点沙箱中处理。
参见:ERROR_PATTERNS.md,其中提供了完整指南——每种错误的错误/正确代码、转义规则、沙箱限制(错误 #6–#7)、预防检查清单,以及快速错误消息查找表。
内置函数与辅助工具
// HTTP requests (no auth — see sandbox note below)
const res = await this.helpers.httpRequest({ method: 'GET', url: 'https://api.example.com/data' });
// DateTime (Luxon): now, formatting, arithmetic
const now = DateTime.now();
const formatted = now.toFormat('yyyy-MM-dd');
const tomorrow = now.plus({ days: 1 });
// $jmespath() — query JSON structures
const adults = $jmespath($input.first().json, 'users[?age >= `18`]');
// $getWorkflowStaticData() — data that persists across executions
**沙箱(自 n8n v2.0 起,JsTaskRunnerSandbox):**访问器是 this.helpers.httpRequest()——这里的 $helpers 全局变量未定义($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 → “最佳实践”,其中提供了每项实践的代码示例。
生产环境注意事项
从真实部署中总结出的宝贵经验,详见 DATA_ACCESS.md → “生产环境注意事项”:
- SplitInBatches 的输出容易让人误解:
main[0]= 完成(所有批次处理完后触发一次),main[1]= 每个批次(循环体)。在完成输出后添加一个 Limit 1 节点以确保安全。 - 迭代次数决定成本:每次循环迭代都会通过引擎重新运行整个循环体(每次约有 0.8 ms 的开销)。
batchSize: 1相当于 Each Item 循环——应使用实际限制(速率限制、页面大小、内存)允许的最大批次大小,或者完全不循环。 - 跨迭代累积(重要):循环结束后,
$('Node Inside Loop').all()仅返回最后一次迭代的项目。请通过$getWorkflowStaticData('global')进行累积(之前重置、循环内推入、之后读取)。 - pairedItem:输出与输入不一一对应的项目时,需设置
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–10 ms;而 Code 节点在沙箱中运行约需 500–1000 ms——对于纯粹的单项目整形,速度相差约 100 倍,且功能并无区别。只有在需要聚合整个数据集(
$input.all())、使用允许列表中的库,或执行异步工作时,Code 节点才值得使用。在编写加密(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(无需
{{ }}) - 了解何时使用表达式、何时使用代码
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 与 Each Item)
- 语言选择(JavaScript 与 Python)
- 了解属性依赖关系
n8n Workflow Patterns:
- 在转换步骤中使用 Code 节点
- Webhook → Code → API 模式
- 在工作流中处理错误
n8n Validation Expert:
- 验证 Code 节点配置
- 处理验证错误
- 自动修复常见问题
快速参考清单
部署 Code 节点前,请确认:
- 代码不为空 - 必须包含有意义的逻辑
- 存在 return 语句 - 返回 items,而不是原始值或
null - 采用规范的返回格式 - 每个 item:
{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 了! 从简单的转换开始,使用错误模式指南避免常见问题,并参考模式库中的生产就绪示例。