选择节点构建方式#
n8n 提供两种节点构建风格:声明式(declarative)和编程式(programmatic)。
大多数节点建议使用声明式风格,这种风格:
- 采用基于 JSON 的语法,编写更简单,引入错误的风险更低
- 更具未来兼容性
- 支持与 REST API 集成
编程式风格更为冗长。以下情况必须使用编程式风格:
- 触发器节点(Trigger nodes)
- 非基于 REST 的节点(包括需要调用 GraphQL API 的节点和使用外部依赖的节点)
- 需要转换输入数据的节点
- 完整版本控制。有关版本控制类型的更多信息,请参阅节点版本控制
数据处理差异#
声明式与编程式风格的主要区别在于处理输入数据和构建 API 请求的方式。编程式风格需要实现 execute() 方法,该方法负责读取输入数据和参数,然后构建请求。声明式风格则通过 operations 对象中的 routing 键来处理这些操作。有关节点参数和 execute() 方法的更多信息,请参阅节点基础文件。
语法差异#
通过对比以下两个代码片段可以理解声明式与编程式风格的区别。本例创建了 SendGrid 集成的一个简化版本,称为 "FriendGrid"。以下代码片段并不完整,主要突出节点构建风格的差异。
编程式风格:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93| ``` import{ IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, IRequestOptions, }from'n8n-workflow';
```typescript
import { INodeType, INodeTypeDescription } from 'n8n-workflow';
// 创建 FriendGrid 类
export class FriendGrid implements INodeType {
description: INodeTypeDescription = {
displayName: 'FriendGrid',
name: 'friendGrid',
...
// 设置基本请求配置
requestDefaults: {
baseURL: 'https://api.sendgrid.com/v3/marketing'
},
properties: [
{
displayName: 'Resource',
...
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'contact',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: '创建联系人',
// 添加路由对象
routing: {
request: {
method: 'POST',
url: '=/contacts',
send: {
type: 'body',
properties: {
email: {{$parameter["email"]}}
}
}
}
},
// 处理联系人创建的响应
output: {
postReceive: [
{
type: 'set',
properties: {
value: '={{ { "success": $response } }}'
}
}
]
}
},
],
default: 'create',
description: '要执行的操作',
},
{
displayName: 'Email',
...
},
{
displayName: 'Additional Fields',
// 设置可选字段
},
],
}
// 无需 execute 方法
}以声明式风格:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74| ```typescript import { INodeType, INodeTypeDescription } from 'n8n-workflow';
// 创建 FriendGrid 类 export class FriendGrid implements INodeType { description: INodeTypeDescription = { displayName: 'FriendGrid', name: 'friendGrid', ... properties: [ { displayName: 'Resource', ... }, { displayName: 'Operation', name: 'operation', type: 'options', displayOptions: { show: { resource: [ 'contact', ], }, }, options: [ { name: 'Create', value: 'create', description: '创建联系人', }, ], default: 'create', description: '要执行的操作', }, { displayName: 'Email', name: 'email', ... }, { displayName: 'Additional Fields', // 设置可选字段 }, ], };
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
let responseData;
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
// 获取用户为此节点提供的凭据
const credentials = await this.getCredentials('friendGridApi') as IDataObject;
if (resource === 'contact') {
if (operation === 'create') {
// 获取邮箱输入
const email = this.getNodeParameter('email', 0) as string;
// 获取附加字段输入
const additionalFields = this.getNodeParameter('additionalFields', 0) as IDataObject;
const data: IDataObject = {
email,
};
Object.assign(data, additionalFields);
// 按照 https://sendgrid.com/docs/api-reference/ 中的定义发起 HTTP 请求
const options: IRequestOptions = {
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${credentials.apiKey}`,
},
method: 'PUT',
body: {
contacts: [
data,
],
},
url: `https://api.sendgrid.com/v3/marketing/contacts`,
json: true,
};
responseData = await this.helpers.httpRequest(options);
}
}
// 将数据映射到 n8n 数据格式
return [this.helpers.returnJsonArray(responseData)];
}}
---|---