mirror of
https://github.com/n8n-io/n8n-nodes-starter.git
synced 2025-10-29 14:22:26 -05:00
I observed some weird behaviors when testing a custom node which was used with `continueOnFail()`, and would return the items, as is done in this example. ## Issues: - Records are being pushed in the `items` array within a loop over them, this essentially causes an infinite loop. I fixed that loop by adding `itemCount` - Upon fixing the infinite loop, I noticed both `success` and `error` branches of the node would activate, that was because the pushed item had an `error` field (which triggers the error branch), but the original item was still present without an error field (which trigger the success branch) There may be better fixes to this, but this approach worked for me.
78 lines
2.2 KiB
TypeScript
78 lines
2.2 KiB
TypeScript
import type {
|
|
IExecuteFunctions,
|
|
INodeExecutionData,
|
|
INodeType,
|
|
INodeTypeDescription,
|
|
} from 'n8n-workflow';
|
|
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
|
|
|
|
export class ExampleNode implements INodeType {
|
|
description: INodeTypeDescription = {
|
|
displayName: 'Example Node',
|
|
name: 'exampleNode',
|
|
group: ['transform'],
|
|
version: 1,
|
|
description: 'Basic Example Node',
|
|
defaults: {
|
|
name: 'Example Node',
|
|
},
|
|
inputs: [NodeConnectionType.Main],
|
|
outputs: [NodeConnectionType.Main],
|
|
usableAsTool: true,
|
|
properties: [
|
|
// Node properties which the user gets displayed and
|
|
// can change on the node.
|
|
{
|
|
displayName: 'My String',
|
|
name: 'myString',
|
|
type: 'string',
|
|
default: '',
|
|
placeholder: 'Placeholder value',
|
|
description: 'The description text',
|
|
},
|
|
],
|
|
};
|
|
|
|
// The function below is responsible for actually doing whatever this node
|
|
// is supposed to do. In this case, we're just appending the `myString` property
|
|
// with whatever the user has entered.
|
|
// You can make async calls and use `await`.
|
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
const items = this.getInputData();
|
|
const itemCount = items.length;
|
|
|
|
let item: INodeExecutionData;
|
|
let myString: string;
|
|
|
|
// Iterates over all input items and add the key "myString" with the
|
|
// value the parameter "myString" resolves to.
|
|
// (This could be a different value for each item in case it contains an expression)
|
|
for (let itemIndex = 0; itemIndex < itemCount; itemIndex++) {
|
|
try {
|
|
myString = this.getNodeParameter('myString', itemIndex, '') as string;
|
|
item = items[itemIndex];
|
|
|
|
item.json.myString = myString;
|
|
} catch (error) {
|
|
// This node should never fail but we want to showcase how
|
|
// to handle errors.
|
|
if (this.continueOnFail()) {
|
|
items[itemIndex].error = error;
|
|
} else {
|
|
// Adding `itemIndex` allows other workflows to handle this error
|
|
if (error.context) {
|
|
// If the error thrown already contains the context property,
|
|
// only append the itemIndex
|
|
error.context.itemIndex = itemIndex;
|
|
throw error;
|
|
}
|
|
throw new NodeOperationError(this.getNode(), error, {
|
|
itemIndex,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return [items];
|
|
}
|
|
}
|