substrat.cat
Processos

El node Code d'n8n: transformar dades sense morir-hi

«Run Once for All Items» contra «Run Once for Each Item», $input.all() i $json, el format de retorn i per què triar malament el mode multiplica el temps per trenta.

·8 min de lectura

Una de les tres guies del clúster d’automatització amb n8n. El node Code és el que fa el que cap altre node fa: agrupar, calcular, remodelar dades. També és on la gent es fa un embolic, perquè hi ha dues maneres d’executar-lo i triar la que no toca et pot deixar un flux trenta vegades més lent —o directament trencat.

Primer: sovint no el necessites

Abans del codi, la pregunta honesta. Molt del que la gent posa al node Code ja el fan nodes normals, i millor:

  • Donar forma a les dades, afegir o treure camps → node Edit Fields (Set).
  • Filtrar → node Filter.
  • Bifurcar → IF / Switch.
  • Ajuntar branques → Merge.

El node Code és per al que aquests no arriben: una transformació amb lògica, una agrupació, un càlcul que depèn de diversos items alhora. Si el que fas es pot fer amb un Edit Fields, fes-lo amb Edit Fields: el flux serà més llegible i qualsevol el podrà tocar sense saber JavaScript.

Els dos modes, i per què importen

El node Code té un desplegable, Mode, amb dues opcions. És la decisió més important del node.

Run Once for All Items

El codi s’executa un sol cop, amb tots els items de cop a la mà. La teva eina és $input.all(), que et dona un array amb tots els items d’entrada:

// Agrupar comandes per client i sumar imports
const items = $input.all();
const perClient = {};

for (const item of items) {
  const { client, import: imp } = item.json;
  perClient[client] = (perClient[client] ?? 0) + imp;
}

// Un item de sortida per client
return Object.entries(perClient).map(([client, total]) => ({
  json: { client, total },
}));

Fixa’t en dues coses: item.json és on viuen les dades de cada item, i el return és un array d’objectes amb clau json. Aquest és el format que n8n espera; si tornes una altra cosa, peta.

Run Once for Each Item

El codi s’executa una vegada per cada item. Si n’entren 10, corre 10 cops. Dins, $json és l’item actual —no cal recórrer cap array, ja hi ets:

// S'executa per cada item; $json és aquest item
return { json: { ...$json, iva: $json.import * 0.21 } };

Aquí el return és un sol objecte amb clau json, perquè el node ja s’encarrega de repetir-ho per cada item.

La trampa de rendiment

Aquí és on triar malament es paga. Cada execució de «Run Once for Each Item» té un cost fix de preparació de context. Sobre pocs items no es nota. Sobre molts, sí: mesurat en n8n 2.x amb registres petits, processar 10.000 items en mode «Each Item» són uns 6 segons de pura sobrecàrrega, contra uns 0,2 segons en mode «All Items». Trenta vegades més, i no perquè el teu codi sigui lent, sinó pel mode.

La regla és senzilla: per defecte, All Items. Recorre la llista dins d’un sol node. Reserva «Each Item» per quan un item necessita de veritat estar aïllat —perquè vols gestionar-ne l’error per separat, o perquè fas una crida a una API que no pots agrupar. Fora d’aquests dos casos, All Items sempre.

Accedir a altres nodes des del codi

Dins del node Code tens les mateixes referències que a les expressions:

// Una dada d'un node concret, pel seu nom
const token = $('Configuració').first().json.apiKey;

// Tots els items d'un altre node
const clients = $('Llegir clients').all();

// Variables d'entorn (per a secrets, no els escriguis al codi)
const clau = $env.API_KEY;

$('Nom del node') és el motiu pel qual val la pena posar noms clars als nodes. Un flux ple de «Code», «Code1», «HTTP Request2» és impossible de llegir sis mesos després.

Els tres errors que veig sempre

1. Tornar el format que no toca. En All Items, return ha de ser un array [{ json: {...} }]. Tornar { json: {...} } (sense array) o [{...}] (sense la clau json) fa que el node peti o passi dades buides. És la causa número u de «no entenc per què no funciona».

2. Fer crides a APIs dins del bucle. El node Code pot fer fetch, i és temptador posar-hi un bucle que crida una API per cada item. No ho facis: perds els reintents, la gestió d’errors i el paral·lelisme que et donaria un node HTTP Request. Deixa les crides al node que hi és per a això, i el Code per transformar.

3. Guardar estat entre execucions. El node Code no recorda res entre execucions del flux. Cada cop arrenca net. Si necessites recordar «per on anava», això va a fora —una base de dades, una taula—, no a una variable del codi.

JavaScript o Python

El node Code accepta els dos. JavaScript corre de manera nativa i és el camí ràpid per defecte. Python corre a través de Pyodide (Python compilat a WebAssembly), cosa que afegeix una estona d’arrencada i no porta totes les llibreries. Per a transformacions de dades dins d’un flux, JavaScript és la tria pràctica; si el que vols és feina de dades de veritat, sovint el millor node Code és cap: exporta a una base de dades i fes-ho amb SQL o Python de veritat, que és més ràpid i més fàcil de provar.

En resum

  • Prova primer amb Edit Fields, Filter, IF. El Code és per al que no arriben.
  • All Items per defecte, amb $input.all() i return [{ json }].
  • Each Item només per aïllar de veritat un item.
  • Les crides a API, al node HTTP Request; l’estat, a fora; el càlcul pesat, a la base de dades.

Continua per la gestió d’errors —com protegir els lots que aquí has après a processar— o torna al tronc de la guia d’n8n.

Els detalls dels modes d’execució surten de la documentació del node Code d’n8n.

El següent pas

Tens un procés
que odies fer?

Explica-m'ho i et diré si es pot automatitzar — i si no es pot, també t'ho diré. La primera conversa no es cobra — però el cafè el poses tu.

hola@substrat.cat