mcpField
N
n8n-code-javascript

n8n-code-javascript

github.com/ovachiever开发5651 次安装49 周前更新
代码仓库

关于 n8n-code-javascript

n8n-code-javascript 是一项指导在 n8n Code 节点中编写 JavaScript 的技能,介绍执行模式、数据访问、返回格式、内置辅助函数和常见工作流模式。

主要功能

  1. 01选择合适的执行模式
  2. 02读取输入和其他节点数据
  3. 03按要求返回条目格式
  4. 04使用 HTTP、日期和 JSON 辅助函数
  5. 05应用聚合与转换模式
  6. 06避免常见编码错误

适用场景

  1. 01在工作流中聚合或转换条目
  2. 02解析 Webhook 请求数据
  3. 03在 Code 节点中发起 HTTP 请求
  4. 04验证并排查 Code 节点输出

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ovachiever/droid-tings --skill n8n-code-javascript

安装后在 Claude Code 中输入/n8n-code-javascript确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

BUILTIN_FUNCTIONS.md
COMMON_PATTERNS.md
DATA_ACCESS.md
ERROR_PATTERNS.md
README.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;
基本规则
  1. 选择“Run Once for All Items”模式(大多数使用场景推荐)
  2. 访问数据:$input.all()、$input.first() 或 $input.item
  3. 重要:必须返回 [{json: {...}}] 格式
  4. 重要:Webhook 数据位于 $json.body 下(而不是直接位于 $json 中)
  5. 可用内置功能:$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,而非手动循环
  • 输出一致 - 所有代码路径都返回相同结构

其他资源

相关文件
n8n 文档

准备好在 n8n Code 节点中编写 JavaScript 了! 从简单的转换开始,使用错误模式指南避免常见问题,并参考模式库中的生产就绪示例。

评论

支持 Markdown