JavaScript-Skript

Workflow: JavaScriptCommunity Edition+

Einführung

Der JavaScript-Skript-Knoten ermöglicht es Ihnen, ein benutzerdefiniertes serverseitiges JavaScript-Skript innerhalb eines Workflows auszuführen. Das Skript kann Variablen aus vorgelagerten Schritten des Workflows als Parameter verwenden, und sein Rückgabewert kann nachgelagerten Knoten zur Verfügung gestellt werden.

Das Skript wird in einem Worker-Thread auf dem Server der NocoBase-Anwendung ausgeführt. Standardmäßig verwendet es eine sichere Sandbox (QuickJS auf WebAssembly-Basis), die weder require noch Node.js-Built-in-APIs unterstützt. Details dazu finden Sie unter Ausführungs-Engine und Funktionsliste.

Knoten erstellen

In der Workflow-Konfigurationsoberfläche klicken Sie auf das Plus-Symbol („+“) im Ablauf, um einen „JavaScript“-Knoten hinzuzufügen:

20241202203457

Knotenkonfiguration

20241202203655

Parameter

Hierüber übergeben Sie Variablen oder statische Werte aus dem Workflow-Kontext an das Skript, damit diese in der Skriptlogik verwendet werden können. name ist der Parametername, der nach der Übergabe an das Skript als Variablenname dient. value ist der Parameterwert; Sie können hier eine Variable auswählen oder einen konstanten Wert eingeben.

Skriptinhalt

Der Skriptinhalt kann als Funktion betrachtet werden. Sie können beliebigen JavaScript-Code schreiben, der in der Node.js-Umgebung unterstützt wird, und mit der return-Anweisung einen Wert als Ergebnis der Knotenausführung zurückgeben. Dieser Wert kann dann von nachfolgenden Knoten als Variable verwendet werden.

Nachdem Sie den Code geschrieben haben, können Sie über die Schaltfläche „Testen“ unterhalb des Editors einen Dialog zur Testausführung öffnen. Dort können Sie Parameter mit statischen Werten belegen, um eine simulierte Ausführung durchzuführen. Nach der Ausführung sehen Sie im Dialog den Rückgabewert und den Inhalt der Ausgabe (Logs).

20241202203833

Timeout-Einstellung

Die Einheit sind Millisekunden. Ein Wert von 0 bedeutet, dass kein Timeout festgelegt wird.

Workflow bei Fehler fortsetzen

Wenn diese Option aktiviert ist, werden nachfolgende Knoten auch dann ausgeführt, wenn das Skript einen Fehler aufweist oder ein Timeout auftritt.

Hinweis

Wenn das Skript fehlerhaft ist, gibt es keinen Rückgabewert. Das Ergebnis des Knotens wird stattdessen mit der Fehlermeldung gefüllt. Falls nachfolgende Knoten die Ergebnisvariable des Skriptknotens verwenden, ist hier Vorsicht geboten.

Steuerung der Worker-Parallelität

JavaScript-Skript-Knoten stellen auszuführende Skripte in eine Aufgabenwarteschlange und führen sie in separaten Worker-Threads aus. Standardmäßig begrenzt NocoBase die Parallelität der JavaScript-Skript-Worker nicht. Wenn mehrere Aufgaben in der Warteschlange warten, können sie gleichzeitig Worker erstellen und ausgeführt werden.

Wenn Skripte während der Ausführung viel Arbeitsspeicher beanspruchen, können mehrere Worker den Speicherverbrauch einer Anwendungsinstanz schnell erhöhen. Legen Sie in diesem Fall mit der Umgebungsvariable WORKFLOW_SCRIPT_WORKER_CONCURRENCY eine Parallelitätsgrenze fest. Das Gleiche gilt für CPU-intensive Skripte: Eine zu hohe Parallelität erhöht die CPU-Konkurrenz und kann andere Anfragen und Workflows in NocoBase beeinträchtigen. Sie sollten diese Variable auch konfigurieren, wenn innerhalb kurzer Zeit viele Skriptaufgaben entstehen können:

WORKFLOW_SCRIPT_WORKER_CONCURRENCY=4

Es gelten folgende Regeln:

  • Wenn die Variable nicht konfiguriert oder ihr Wert ungültig ist, ist die Parallelität unbegrenzt
  • Eine positive Ganzzahl legt die maximale Anzahl gleichzeitig ausgeführter Worker-Threads fest
  • Der Wert 0 hebt die Begrenzung auf, sodass alle Aufgaben in der Warteschlange gleichzeitig ausgeführt werden können

Wenn die Parallelitätsgrenze erreicht ist, bleiben neue Aufgaben in der Warteschlange, bis ein Worker verfügbar ist. Wenn Skripte selten ausgeführt werden und jede Ausführung nur wenige Ressourcen benötigt, können Sie die Standardkonfiguration beibehalten. Falls Sie eine Parallelitätsgrenze benötigen, beginnen Sie mit einem kleinen Wert und passen Sie ihn anhand der Arbeitsspeicher- und CPU-Auslastung der Anwendungsinstanz sowie der Wartezeit in der Aufgabenwarteschlange schrittweise an.

Wenn eine Anwendung auf mehreren Serverinstanzen läuft, gilt diese Einstellung für jede Instanz separat. Die gesamte Parallelitätskapazität hängt außerdem von der Anzahl der Instanzen ab, die Aufgaben verarbeiten können. Starten Sie den NocoBase-Dienst nach einer Änderung der Umgebungsvariable neu, damit der neue Wert wirksam wird.

Ausführungs-Engine

Der JavaScript-Skript-Knoten unterstützt zwei Ausführungs-Engines, die automatisch anhand der Konfiguration der Umgebungsvariable WORKFLOW_SCRIPT_MODULES ausgewählt werden:

Sicherer Modus (Standard)

Wenn WORKFLOW_SCRIPT_MODULES nicht konfiguriert ist, werden Skripte mit der QuickJS-Engine auf WebAssembly-Basis ausgeführt. Diese Engine führt Code in einer isolierten JavaScript-Laufzeitumgebung mit folgenden Eigenschaften aus:

  • require wird nicht unterstützt — es können keine Module importiert werden
  • Node.js-Built-in-APIs (wie process, Buffer, global usw.) werden nicht unterstützt
  • Es stehen nur ECMAScript-Standardobjekte zur Verfügung (wie JSON, Math, Promise, Date usw.)
  • Die Übergabe von Daten über Parameter, console für Logging sowie async/await werden unterstützt

Dies ist der empfohlene Standardmodus, geeignet für reine Berechnungs- und Datenverarbeitungslogik, und bietet das höchste Maß an Sicherheitsisolierung.

Unsicherer Modus (Modulunterstützung)

Wenn WORKFLOW_SCRIPT_MODULES konfiguriert ist, wechseln Skripte zur integrierten Node.js-vm-Engine, um die require-Funktionalität zu ermöglichen.

Sicherheitswarnung

Der unsichere Modus verwendet Node.js vm nur, um CommonJS-require zu unterstützen. Das Node.js-vm-Modul ist kein sicherer Sandbox-Mechanismus. Die Aktivierung dieses Modus bedeutet, dass allen Benutzern vertraut wird, die Workflow-Skripte bearbeiten, testen oder ausführen können, als könnten sie Code mit den Berechtigungen des NocoBase-Servers ausführen.

WORKFLOW_SCRIPT_MODULES ist keine Sicherheitsgrenze und kein Berechtigungsmodell. Es steuert nur, welche Modulnamen von require() akzeptiert werden, bevor der Skriptcode ausgeführt wird.

Module können im Skript konsistent mit CommonJS verwendet werden. Module werden im Code mit der require()-Anweisung importiert.

Es werden native Node.js-Module und in node_modules installierte Module (einschließlich der von NocoBase bereits verwendeten Abhängigkeitspakete) unterstützt. Module, die dem Code zur Verfügung stehen sollen, müssen in der Umgebungsvariable WORKFLOW_SCRIPT_MODULES der Anwendung deklariert werden. Mehrere Paketnamen werden durch Kommas getrennt, zum Beispiel:

WORKFLOW_SCRIPT_MODULES=crypto,timers,lodash,dayjs
Hinweis

Module, die nicht in der Umgebungsvariable WORKFLOW_SCRIPT_MODULES deklariert sind, können nicht direkt mit require() importiert werden, selbst wenn sie nativ in Node.js vorhanden oder bereits in node_modules installiert sind. Diese Liste dient nur zur Konfiguration unterstützter Imports. Verlassen Sie sich nicht darauf, um Skriptberechtigungen zu reduzieren oder die Bearbeitung von Skripten sicher an weniger vertrauenswürdige Benutzer zu delegieren.

In einer Umgebung, die nicht aus dem Quellcode bereitgestellt wird, können Sie ein benötigtes Modul, das nicht in node_modules installiert ist, manuell in das storage-Verzeichnis installieren. Wenn Sie beispielsweise das exceljs-Paket verwenden möchten, können Sie die folgenden Schritte ausführen:

cd storage
npm i --no-save --no-package-lock --prefix . exceljs

Fügen Sie dann den relativen (oder absoluten) Pfad des Pakets, basierend auf dem CWD (aktuellen Arbeitsverzeichnis) der Anwendung, zur Umgebungsvariable WORKFLOW_SCRIPT_MODULES hinzu:

WORKFLOW_SCRIPT_MODULES=./storage/node_modules/exceljs

Anschließend können Sie das exceljs-Paket in Ihrem Skript verwenden (der in require verwendete Name muss exakt mit dem in der Umgebungsvariable definierten übereinstimmen):

const ExcelJS = require('./storage/node_modules/exceljs');
// ...

Funktionsliste

Node.js-Version

Entspricht der Node.js-Version, mit der die Hauptanwendung ausgeführt wird.

Globale Variablen

Globale Variablen wie global, process, __dirname und __filename werden nicht unterstützt.

console.log(global); // will throw error: "global is not defined"

Übergebene Parameter

Die im Knoten konfigurierten Parameter werden als globale Variablen im Skript verfügbar und können direkt verwendet werden. An das Skript übergebene Parameter unterstützen nur primitive Typen wie boolean, number, string, object und Arrays. Ein Date-Objekt wird bei der Übergabe in einen ISO-formatierten String umgewandelt. Andere komplexe Typen, wie Instanzen benutzerdefinierter Klassen, können nicht direkt übergeben werden.

Rückgabewert

Mit der return-Anweisung können Sie Daten primitiver Typen (gemäß den Parameterregeln) als Ergebnis an den Knoten zurückgeben. Wenn im Code keine return-Anweisung aufgerufen wird, hat die Knotenausführung keinen Rückgabewert.

return 123;

Ausgabe (Logs)

Die Verwendung von console zur Ausgabe von Logs wird unterstützt.

console.log('hello world!');

Bei der Ausführung des Workflows wird die Ausgabe des Skriptknotens auch in der Logdatei des entsprechenden Workflows protokolliert.

Asynchronität

Die Definition asynchroner Funktionen mit async und deren Aufruf mit await wird unterstützt. Ebenso wird die Verwendung des globalen Promise-Objekts unterstützt.

async function test() {
  return Promise.resolve(1);
}

const value = await test();
return value;

Timer

Um Methoden wie setTimeout, setInterval oder setImmediate zu verwenden, müssen Sie diese aus dem Node.js timers-Paket importieren (nur im unsicheren Modus verfügbar).

const { setTimeout, setInterval, setImmediate, clearTimeout, clearInterval, clearImmediate } = require('timers');

async function sleep(time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

await sleep(1000);

return 123;