关于 n8n-code-javascript
n8n-code-javascript 是一项指导在 n8n Code 节点中编写 JavaScript 的技能,介绍执行模式、数据访问、返回格式、内置辅助函数和常见工作流模式。
主要功能
- 01选择合适的执行模式
- 02读取输入和其他节点数据
- 03按要求返回条目格式
- 04使用 HTTP、日期和 JSON 辅助函数
- 05应用聚合与转换模式
- 06避免常见编码错误
适用场景
- 01在工作流中聚合或转换条目
- 02解析 Webhook 请求数据
- 03在 Code 节点中发起 HTTP 请求
- 04验证并排查 Code 节点输出
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ovachiever/ droid-tings --skill n8n-code-javascript安装后在 Claude Code 中输入/n8n-code-javascript确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
BUILTIN_FUNCTIONS.mdCOMMON_PATTERNS.mdDATA_ACCESS.mdERROR_PATTERNS.mdREADME.md详细介绍
JavaScript 代码节点
在 n8n 代码节点中编写 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;
基本规则
- 选择“Run Once for All Items”模式(大多数使用场景推荐)
- 访问数据:
$input.all()、$input.first()或$input.item - 重要:必须返回
[{json: {...}}]格式 - 重要:Webhook 数据位于
$json.body下(而不是直接位于$json中) - 可用内置功能:$helpers.httpRequest()、DateTime(Luxon)、$jmespath()
模式选择指南
代码节点提供两种执行模式。请根据使用场景选择:
Run Once for All Items(推荐 - 默认)
适用于: 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
}
}];
适用场景:
- ✅ 比较数据集中的多个条目
- ✅ 计算总和、平均值或统计数据
- ✅ 对条目排序或排名
- ✅ 去重
- ✅ 生成聚合报告
- ✅ 合并多个条目中的数据
Run Once for Each Item
适用于: 仅限特殊场景
- 工作方式:针对每个输入条目分别执行代码
- 数据访问:
$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”模式
- 每个条目完全独立? → 使用“Each Item”模式
- 不确定? → 使用“All Items”模式(也可以随时在内部循环)
数据访问模式
模式 1:$input.all() - 最常见
适用场景:处理数组、批量操作、聚合
// Get all items from previous node
const allItems = $input.all();
// Filter, map, reduce as needed
const valid = allItems.filter(item => item.json.status === 'active');
const mapped = valid.map(item => ({
json: {
id: item.json.id,
name: item.json.name
}
}));
return mapped;
模式 2:$input.first() - 很常见
适用场景:处理单个对象、API 响应、先进先出数据
// Get first item only
const firstItem = $input.first();
const data = firstItem.json;
return [{
json: {
result: processData(data),
processedAt: new Date().toISOString()
}
}];
模式 3:$input.item - 仅限 Each Item 模式
适用场景:使用“Run Once for Each Item”模式
// Current item in loop (Each Item mode only)
const currentItem = $input.item;
return [{
json: {
...currentItem.json,
itemProcessed: true
}
}];
模式 4:$node - 引用其他节点
适用场景:需要获取工作流中特定节点的数据
// Get output from specific node
const webhookData = $node["Webhook"].json;
const httpData = $node["HTTP Request"].json;
return [{
json: {
combined: {
webhook: webhookData,
api: httpData
}
}
}];
参见:DATA_ACCESS.md,了解完整指南
重要: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 属性的对象数组
正确的返回格式
// ✅ 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 [];
}
错误的返回格式
// ❌ WRONG: Object without array wrapper
return {
json: {field: value}
};
// ❌ WRONG: Array without json wrapper
return [{field: value}];
// ❌ WRONG: Plain string
return "processed";
// ❌ WRONG: Raw data without mapping
return $input.all(); // Missing .map()
// ❌ WRONG: Incomplete structure
return [{data: value}]; // Should be {json: value}
重要性:后续节点需要数组格式。格式不正确会导致工作流执行失败。
参见:ERROR_PATTERNS.md #3,了解详细的错误解决方案
常见模式概览
根据生产工作流,以下是最实用的模式:
1. 多源数据聚合
合并来自多个 API、Webhook 或节点的数据
const allItems = $input.all();
const results = [];
for (const item of allItems) {
const sourceName = item.json.name || 'Unknown';
// Parse source-specific structure
if (sourceName === 'API1' && item.json.data) {
results.push({
json: {
title: item.json.data.title,
source: 'API1'
}
});
}
}
return results;
2. 使用正则表达式筛选
从文本中提取模式、提及内容或关键词
const pattern = /\b([A-Z]{2,5})\b/g;
const matches = {};
for (const item of $input.all()) {
const text = item.json.text;
const found = text.match(pattern);
if (found) {
found.forEach(match => {
matches[match] = (matches[match] || 0) + 1;
});
}
}
return [{json: {matches}}];
3. 数据转换与增强
映射字段、规范格式、添加计算字段
const items = $input.all();
return items.map(item => {
const data = item.json;
const nameParts = data.name.split(' ');
return {
json: {
first_name: nameParts[0],
last_name: nameParts.slice(1).join(' '),
email: data.email,
created_at: new Date().toISOString()
}
};
});
4. Top N 筛选与排名
对结果排序并限制数量
const items = $input.all();
const topItems = items
.sort((a, b) => (b.json.score || 0) - (a.json.score || 0))
.slice(0, 10);
return topItems.map(item => ({json: item.json}));
5. 聚合与报告
对数据求和、计数、分组
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,
timestamp: new Date().toISOString()
}
}];
参见:COMMON_PATTERNS.md,了解 10 种详细的生产模式
错误预防 - 五大常见错误
#1:代码为空或缺少返回值(最常见)
// ❌ WRONG: No return statement
const items = $input.all();
// ... processing code ...
// Forgot to return!
// ✅ CORRECT: Always return data
const items = $input.all();
// ... processing ...
return items.map(item => ({json: item.json}));
#2:表达式语法混淆
// ❌ WRONG: Using n8n expression syntax in code
const value = "{{ $json.field }}";
// ✅ CORRECT: Use JavaScript template literals
const value = `${$json.field}`;
// ✅ CORRECT: Direct access
const value = $input.first().json.field;
#3:返回值包装格式不正确
// ❌ WRONG: Returning object instead of array
return {json: {result: 'success'}};
// ✅ CORRECT: Array wrapper required
return [{json: {result: 'success'}}];
#4:缺少空值检查
// ❌ WRONG: Crashes if field doesn't exist
const value = item.json.user.email;
// ✅ CORRECT: Safe access with optional chaining
const value = item.json?.user?.email || '[email protected]';
// ✅ CORRECT: Guard clause
if (!item.json.user) {
return [];
}
const value = item.json.user.email;
#5:Webhook 请求体嵌套
// ❌ WRONG: Direct access to webhook data
const email = $json.email;
// ✅ CORRECT: Webhook data under .body
const email = $json.body.email;
参见:ERROR_PATTERNS.md,获取全面的错误指南
内置函数和辅助工具
$helpers.httpRequest()
在代码中发起 HTTP 请求:
const response = await $helpers.httpRequest({
method: 'GET',
url: 'https://api.example.com/data',
headers: {
'Authorization': 'Bearer token',
'Content-Type': 'application/json'
}
});
return [{json: {data: response}}];
DateTime (Luxon)
日期和时间操作:
// Current time
const now = DateTime.now();
// Format dates
const formatted = now.toFormat('yyyy-MM-dd');
const iso = now.toISO();
// Date arithmetic
const tomorrow = now.plus({days: 1});
const lastWeek = now.minus({weeks: 1});
return [{
json: {
today: formatted,
tomorrow: tomorrow.toFormat('yyyy-MM-dd')
}
}];
$jmespath()
查询 JSON 结构:
const data = $input.first().json;
// Filter array
const adults = $jmespath(data, 'users[?age >= `18`]');
// Extract fields
const names = $jmespath(data, 'users[*].name');
return [{json: {adults, names}}];
参见:BUILTIN_FUNCTIONS.md,获取完整参考
最佳实践
1. 始终验证输入数据
const items = $input.all();
// Check if data exists
if (!items || items.length === 0) {
return [];
}
// Validate structure
if (!items[0].json) {
return [{json: {error: 'Invalid input format'}}];
}
// Continue processing...
2. 使用 Try-Catch 处理错误
try {
const response = await $helpers.httpRequest({
url: 'https://api.example.com/data'
});
return [{json: {success: true, data: response}}];
} catch (error) {
return [{
json: {
success: false,
error: error.message
}
}];
}
3. 优先使用数组方法而非循环
// ✅ GOOD: Functional approach
const processed = $input.all()
.filter(item => item.json.valid)
.map(item => ({json: {id: item.json.id}}));
// ❌ SLOWER: Manual loop
const processed = [];
for (const item of $input.all()) {
if (item.json.valid) {
processed.push({json: {id: item.json.id}});
}
}
4. 尽早筛选,延后处理
// ✅ GOOD: Filter first to reduce processing
const processed = $input.all()
.filter(item => item.json.status === 'active') // Reduce dataset first
.map(item => expensiveTransformation(item)); // Then transform
// ❌ WASTEFUL: Transform everything, then filter
const processed = $input.all()
.map(item => expensiveTransformation(item)) // Wastes CPU
.filter(item => item.json.status === 'active');
5. 使用描述性变量名
// ✅ GOOD: Clear intent
const activeUsers = $input.all().filter(item => item.json.active);
const totalRevenue = activeUsers.reduce((sum, user) => sum + user.json.revenue, 0);
// ❌ BAD: Unclear purpose
const a = $input.all().filter(item => item.json.active);
const t = a.reduce((s, u) => s + u.json.revenue, 0);
6. 使用 console.log() 调试
// Debug statements appear in browser console
const items = $input.all();
console.log(`Processing ${items.length} items`);
for (const item of items) {
console.log('Item data:', item.json);
// Process...
}
return result;
何时使用 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_essentials("nodes-base.code") - 验证代码:
validate_node_operation()
n8n Node Configuration:
- 模式选择(All Items 或 Each Item)
- 语言选择(JavaScript 或 Python)
- 了解属性依赖关系
n8n Workflow Patterns:
- 在转换步骤中使用 Code 节点
- Webhook → Code → API 模式
- 工作流中的错误处理
n8n Validation Expert:
- 验证 Code 节点配置
- 处理验证错误
- 自动修复常见问题
快速参考清单
部署 Code 节点前,请确认:
- 代码非空 - 必须包含有意义的逻辑
- 存在返回语句 - 必须返回对象数组
- 返回格式正确 - 每一项的格式为:
{json: {...}} - 数据访问正确 - 使用
$input.all()、$input.first()或$input.item - 不使用 n8n 表达式 - 使用 JavaScript 模板字面量:
`${value}` - 错误处理完善 - 对空值或 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 了! 从简单的转换开始,使用错误模式指南避免常见问题,并参考模式库中的生产就绪示例。