Skip to content

选择你的节点构建方法#

¥Choose your node building approach

n8n 提供两种节点构建方式:声明式和编程式。

¥n8n has two node-building styles, declarative and programmatic.

你应该对大多数节点使用声明式风格。此样式:

¥You should use the declarative style for most nodes. This style:

  • 使用基于 JSON 的语法,编写更简单,引入错误的风险更低。

¥Uses a JSON-based syntax, making it simpler to write, with less risk of introducing bugs.

  • 更具前瞻性。

¥Is more future-proof.

  • 支持与 REST API 集成。

¥Supports integration with REST APIs.

程序化方式更加冗长。以下操作必须使用程序化方式:

¥The programmatic style is more verbose. You must use the programmatic style for:

  • 触发器节点

¥Trigger nodes

  • 任何非基于 REST 的节点。这包括需要调用 GraphQL API 的节点和使用外部依赖的节点。

¥Any node that isn't REST-based. This includes nodes that need to call a GraphQL API and nodes that use external dependencies.

  • 任何需要转换传入数据的节点。

¥Any node that needs to transform incoming data.

  • 完整版本控制。有关版本控制类型的更多信息,请参阅 节点版本控制

¥Full versioning. Refer to Node versioning for more information on types of versioning.

数据处理差异#

¥Data handling differences

声明式和程序式风格的主要区别在于它们处理传入数据和构建 API 请求的方式。程序化方式需要一个 execute() 方法,该方法读取传入的数据和参数,然后构建请求。声明式风格使用 operations 对象中的 routing 键来处理此请求。有关节点参数和 execute() 方法的更多信息,请参阅 节点基础文件

¥The main difference between the declarative and programmatic styles is how they handle incoming data and build API requests. The programmatic style requires an execute() method, which reads incoming data and parameters, then builds a request. The declarative style handles this using the routing key in the operations object. Refer to Node base file for more information on node parameters and the execute() method.

语法差异#

¥Syntax differences

要了解声明式和程序式风格之间的区别,请比较以下两个代码片段。此示例创建了一个名为 "FriendGrid." 的简化版 SendGrid 集成。以下代码片段并不完整:它们用于强调节点构建方式的差异。

¥To understand the difference between the declarative and programmatic styles, compare the two code snippets below. This example creates a simplified version of the SendGrid integration, called "FriendGrid." The following code snippets aren't complete: they emphasize the differences in the node building styles.

程序化风格:

¥In programmatic style:

 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';

// Create the FriendGrid class
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: 'Create a contact',
          },
        ],
        default: 'create',
        description: 'The operation to perform.',
      },
      {
        displayName: 'Email',
        name: 'email',
        . . .
      },
      {
        displayName: 'Additional Fields',
        // Sets up optional 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;
    //Get credentials the user provided for this node
    const credentials = await this.getCredentials('friendGridApi') as IDataObject;

    if (resource === 'contact') {
      if (operation === 'create') {
      // Get email input
      const email = this.getNodeParameter('email', 0) as string;
      // Get additional fields input
      const additionalFields = this.getNodeParameter('additionalFields', 0) as IDataObject;
      const data: IDataObject = {
          email,
      };

      Object.assign(data, additionalFields);

      // Make HTTP request as defined in https://sendgrid.com/docs/api-reference/
      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);
      }
    }
    // Map data to n8n data
    return [this.helpers.returnJsonArray(responseData)];
  }
}

声明式风格:

¥In declarative style:

 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
import { INodeType, INodeTypeDescription } from 'n8n-workflow';

// Create the FriendGrid class
export class FriendGrid implements INodeType {
  description: INodeTypeDescription = {
    displayName: 'FriendGrid',
    name: 'friendGrid',
    . . .
    // Set up the basic request configuration
    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: 'Create a contact',
            // Add the routing object
            routing: {
              request: {
                method: 'POST',
                url: '=/contacts',
                send: {
                  type: 'body',
                  properties: {
                    email: {{$parameter["email"]}}}
                }
              }
            },
            // Handle the response to contact creation
            output: {
              postReceive: [
                {
                  type: 'set',
                  properties: {
                    value: '={{ { "success": $response }}}'
                  }
                }
              ]
            }
          },
        ],
        default: 'create',
        description: 'The operation to perform.',
      },
      {
        displayName: 'Email',
        . . .
      },
      {
        displayName: 'Additional Fields',
        // Sets up optional fields
      },
    ],
  }
  // No execute method needed
}