引言
在 N8N 大学(n8ndx.com)的后台,笔者每天都会收到无数关于 Function 节点的提问。老实说,n8n 的可视化拖拽虽然强大,但一旦遇到稍微复杂的数据处理,比如把一个乱七八糟的 JSON 对象重新排列,或者计算一堆数字的总和,光靠配置节点往往事倍功半。
这时候,Function 节点就是你的“瑞士军刀”。它允许你直接写原生 JavaScript,彻底掌控数据流。但很多刚入门的小伙伴一看到代码就头大。其实,你不需要成为 JS 大神,只需要掌握下面这三行核心代码,就能解决 80% 的常见数据处理难题。
今天,笔者就带你拆解这三个“万金油”代码片段,让你在 n8n 里也能写出优雅且高效的自动化。
代码片段一:数据格式转换(Array.map)
在 n8n 中,最常见的操作就是“遍历”。比如,你从 API 拉取了一张用户列表,但只需要提取每个人的 ID 和名字发给另一个接口。这时候,`Array.map()` 是你的首选。
它会遍历数组中的每一项,返回一个新的数组,而不会改变原数组。这在数据清洗中极其重要。
实战场景
假设输入数据(Input JSON)长这样:
{
"users": [
{ "id": 1, "name": "张三", "age": 25, "email": "zhang@example.com" },
{ "id": 2, "name": "李四", "age": 30, "email": "li@example.com" }
]
}
三行核心代码
在 Function 节点中,你可以这样写:
const rawUsers = $input.first().json.users;
const simplifiedUsers = rawUsers.map(user => ({ id: user.id, name: user.name }));
return { json: simplifiedUsers };
代码解析:
- 第一行:从输入数据中获取
users数组。 - 第二行:使用
map方法,将每个user对象解构,只保留id和name。 - 第三行:将处理后的数组作为新的 JSON 输出。
这三行代码能帮你瞬间把一堆冗余数据瘦身,让后续节点处理起来轻盈无比。
代码片段二:条件过滤与筛选(Array.filter)
很多场景下,你不需要所有数据,只想通过“过滤器”留下关键信息。比如,只保留状态为“成功”的订单,或者只筛选出特定地区的用户。
这时候,Array.filter() 登场。它会创建一个新数组,包含所有通过测试的元素。
实战场景
假设输入数据包含一批订单,你想只处理金额大于 100 的订单:
{
"orders": [
{ "order_id": "A001", "amount": 50, "status": "paid" },
{ "order_id": "A002", "amount": 150, "status": "paid" },
{ "order_id": "A003", "amount": 200, "status": "failed" }
]
}
三行核心代码
在 Function 节点中,你可以这样写:
const orders = $input.first().json.orders;
const highValueOrders = orders.filter(order => order.amount > 100);
return { json: highValueOrders };
代码解析:
- 第一行:获取订单数据。
- 第二行:
filter接受一个函数,只要返回true,该项就会被保留。这里我们只保留金额大于 100 的订单。 - 第三行:输出过滤后的结果。
注意:如果过滤后数组为空,n8n 通常会停止执行后续节点(取决于你的设置),这正好可以用来拦截无效数据流。
代码片段三:键值重组与对象操作(Object.entries / reduce)
这是稍微进阶但极其强大的操作。有时候 API 返回的数据结构很怪,比如把属性名作为 Key,你需要把它转成标准的列表格式。或者,你需要把多个对象的值合并计算。
这里我们用 Object.entries 配合 reduce。虽然看起来像两行,但其实是一个逻辑整体。
实战场景
假设输入数据是一个“键值对”结构,你想把它转成列表:
{
"metrics": {
"2023-01": 100,
"2023-02": 120,
"2023-03": 150
}
}
三行核心代码
在 Function 节点中,你可以这样写:
const metrics = $input.first().json.metrics;
const result = Object.entries(metrics).map(([date, value]) => ({ date, value }));
return { json: result };
代码解析:
- 第一行:获取原始数据。
- 第二行:
Object.entries把对象变成[[key, value], ...]的数组,然后map重新组装成我们想要的对象格式。 - 第三行:输出标准的 JSON 列表,方便表格展示或数据库写入。
这一招在处理聚合数据、统计报表时简直是救命稻草。
避坑指南:Function 节点的常见误区
虽然 JS 很灵活,但在 n8n 的 Function 节点里,有几个坑笔者必须提醒你,否则代码跑不通你会怀疑人生。
1. 必须显式返回数据
在 n8n 的 Function 节点中,你不能像写普通脚本那样只打印 console.log。你必须使用 return 语句将数据传递给下一个节点。
正确的写法是:
return { json: { key: "value" } };
或者返回多个项目:
return [{ json: { key: "a" } }, { json: { key: "b" } }];
2. 理解 $input 的使用
n8n 的 n8n 的上下文对象非常关键。在较新版本中,推荐使用 $input.first().json 来获取第一条输入数据。如果你处理的是二进制数据,路径会有所不同。初学者最容易犯的错就是直接写 input.json,这在新版中可能无法识别。
3. 异步处理
Function 节点默认支持同步代码。如果你需要在节点内进行复杂的异步操作(比如发送 HTTP 请求),记得使用 async/await,但一般情况下,简单的数据转换不需要这么复杂,保持同步代码更易于维护。
FAQ 问答
Q1: Function 节点和 Set 节点有什么区别?
A: Set 节点适合简单的键值赋值或重命名,操作简单且可视化。Function 节点适合复杂的逻辑判断、循环遍历和数学计算。简单说,Set 用来“改名”,Function 用来“变形”。
Q2: 写 JS 代码会拖慢 n8n 的执行速度吗?
A: 对于几百条数据的处理,性能损耗几乎可以忽略不计。但如果你在单个 Function 节点内处理成千上万条数据的复杂运算,可能会有延迟。这时建议拆分流程,或使用专门的数据库节点进行预处理。
Q3: 如何调试 Function 节点里的代码?
A: 最简单的方法是使用 console.log() 打印变量,然后在 n8n 的执行历史(Execution History)中查看全量日志。虽然没有 IDE 的断点调试那么强大,但足以定位大多数问题。
总结与资源
掌握 map、filter 和 Object.entries 这三个核心操作,你基本上就能在 n8n 的世界里横着走了。代码并不神秘,它只是帮你用更灵活的方式去指挥数据。
如果你在 n8n 的使用过程中遇到了其他棘手的问题,或者想学习更高级的节点技巧,欢迎访问 N8N 大学(n8ndx.com)。在这里,我们不讲空洞的理论,只分享能落地的实战经验。祝你的自动化之路顺畅无阻!