你写的n8n Function节点JavaScript代码,为什么老是报错?

2026-01-28 11 0

问题复现:那些让你抓狂的红色报错

作为 N8N大学 的首席主编,笔者见过太多新手在 Function 节点面前败下阵来。你满心欢喜地拖拽出一个 Function 节点,准备用 JavaScript 大展拳脚,结果一运行,满屏的红色错误提示瞬间让你头大。

最常见的报错大概长这样:Cannot read property 'xxx' of undefined 或者 ReferenceError: items is not defined。这些错误看似五花八门,但归根结底,往往是因为你没搞懂 n8n Function 节点的运行机制。

笔者注:n8n 的 Function 节点不是普通的浏览器环境,也不是 Node.js 的原生环境,它是一个高度封装的沙盒。用错语法,报错是必然的。

原因分析:为什么你的代码总是“水土不服”?

用大白话说,n8n 的 Function 节点是基于 vm2 或类似的沙盒技术运行的。这意味着它有自己的作用域和规则,不能完全照搬你在 VS Code 里写的 Node.js 代码。

报错的主要原因通常有以下三点:

  • 作用域污染:你试图访问全局变量,但在 n8n 的沙盒里,很多全局对象是不可见的。
  • 异步处理不当:JavaScript 是单线程的,如果你在 Function 节点里写了复杂的异步逻辑却没正确处理 Promise,数据流就会断掉。
  • 数据结构理解错误:n8n 的数据在节点间传递是 JSON 格式的,如果你直接操作 items[0].json 而不检查它是否存在,一旦上游节点没数据,直接就崩了。

解决方案:从入门到精通的三步走

别急,下面笔者带你一步步解决这些报错。我们从最简单的配置开始,直到写出健壮的代码。

第一招:学会“抄作业”——正确使用示例代码

n8n 官方其实提供了很多示例,但很多新手直接复制粘贴就报错。为什么?因为示例代码通常是针对特定数据结构的。

避坑指南: 当你复制一段代码时,先看懂它在操作什么。

  • 如果代码里是 item.json.name,请确保你的上游节点输出的 JSON 里真的有 name 字段。
  • 如果你不知道上游输出什么,先加一个 Debug 节点 或者 Set 节点,看看数据到底长什么样。

第二招:掌握 n8n 的数据模型——$item() 和 .json

这是 n8n Function 节点最核心的概念。n8n 的数据流是以“Item”(条目)为单位的。你的代码必须显式地处理这些 Item。

一个标准的、不会报错的结构通常是这样的:

// 遍历每一个传入的 item
for (const item of $input.all()) {
  // 读取数据
  let rawData = item.json;
  
  // 处理逻辑(例如:修改字段)
  rawData.new_field = "我是新值";
  
  // 必须返回 item,否则数据会丢失
  return item;
}

或者更简洁的写法(推荐):

return $input.all().map(item => {
  item.json.processed = true;
  return item;
});

重点: 如果你不使用 $input.all() 或者 $item(),而是直接写 items[0],在某些 n8n 版本或特定配置下,你很可能遇到 items is not defined 的错误。

第三招:处理异步与外部请求

如果你需要在 Function 节点里调用外部 API,你必须使用 async/await。但是,n8n 原生不支持在 Function 节点里直接使用 axiosfetch

如果你强行引入 require('axios'),大概率会报错 Cannot find module

正确的做法:

  1. 如果需要外部请求,尽量使用 HTTP Request 节点,因为它自带重试、分页和错误处理机制。
  2. 如果非要在 Function 节点里做复杂逻辑,确保你的代码是同步的,或者使用 n8n 支持的沙盒 API(虽然有限)。
  3. 处理错误:使用 try...catch 包裹你的逻辑,防止整个 Workflow 因为一个数据报错而停滞。
try {
  // 你的逻辑
  let value = item.json.some_deep_property.nested.value;
  // ...
} catch (error) {
  // 捕获错误并记录,而不是让程序崩溃
  console.error("处理 item 失败:", error.message);
  // 可以选择跳过这个 item,或者标记它
  return item;
}

预防措施:如何写出“不报错”的健壮代码

在 N8N大学 的实战经验里,预防报错的核心在于 防御性编程

1. 空值检查(Null Check)
在访问深层嵌套属性前,永远先确认父级是否存在。

// 错误写法
let city = item.json.user.address.city; // 如果 address 为 null,直接报错

// 正确写法
let city = item.json.user && item.json.user.address ? item.json.user.address.city : 'Unknown';
// 或者使用可选链(如果 n8n 环境支持)
let city = item.json.user?.address?.city || 'Unknown';

2. 数据类型转换
n8n 传过来的字符串数字,不会自动转为数字。计算前先转换。

let price = Number(item.json.price);
if (isNaN(price)) price = 0;

3. 善用 Code 节点而非 Function 节点
n8n 新版(0.x 及 1.x)中,Code 节点(使用 JavaScript)逐渐取代了旧版的 Function 节点。如果你还在用旧版,请尝试切换到 Code 节点,它的 API 更现代,更接近 Node.js 原生体验。

FAQ 问答:你可能还想问

Q1: 为什么我写的 console.log 在日志里看不到?

在 n8n 的 Function 节点中,console.log 通常只会打印到 n8n 的后台控制台(如果你是 Docker 部署,就是容器的 logs),而不会显示在 UI 界面的 Debug 节点里。想在 UI 看结果,请使用 return item; 把数据传出去,或者使用 Debug 节点 显示数据。

Q2: 我想在 Function 节点里读取数据库,怎么办?

不推荐。Function 节点不应该承担重型计算或数据库连接的任务。这会阻塞 n8n 的主线程。正确的做法是使用 Postgres/MySQL 节点 或者 SSH 节点 来执行查询,将结果交给 Function 节点处理。

Q3: 代码在测试时没问题,正式运行就报错?

这通常是因为数据量级不同。测试时可能只有 1 条数据,正式运行有 100 条。如果你的代码里有全局变量(例如在循环外定义计数器),可能会因为作用域问题导致数据串扰。确保你的逻辑是无状态的,或者正确管理状态。

总结与资源

n8n 的 Function 节点是把双刃剑,用好了能处理极其复杂的逻辑,用不好就是报错的无底洞。记住笔者的核心建议:理解数据结构、做好空值检查、善用 $input API

如果你在 n8n 的使用过程中还有其他疑难杂症,欢迎访问 N8N大学 (n8ndx.com),这里有更多实战案例和避坑指南等着你。

相关文章

n8n Wait节点在数据同步中的延迟控制实战
n8n Wait节点免费版:我能用它实现定时任务吗?
n8n Error Handling节点:当自动化流程“翻车”时,如何让它自动“扶起来”?
n8n Error Handling节点报错常见问题解决
当n8n流程意外中断,Error Handling节点如何配置才能优雅降级?
n8n Error Handling节点和Try/Catch节点,到底该怎么选?

发布评论