Menu

Node.js readline: Benutzereingaben im Terminal lesen

Node.js hat keine prompt()-Funktion. Um dem Nutzer im Terminal eine Frage zu stellen, erstellst du ein readline-Interface auf process.stdin und rufst question() auf, oder du wartest mit readline/promises per await darauf.

Diese Seite enthält ausführbare Editoren. Bearbeiten, ausführen und Ausgabe sofort sehen.

Um in Node.js Benutzereingaben zu lesen, erstellst du ein readline-Interface auf process.stdin und fragst mit rl.question(). Node.js hat kein prompt(): Die Browservariante öffnet einen Dialog, und ein Terminalprogramm hat keinen. Die moderne Form nutzt readline/promises, wo await rl.question('Name? ') die Zeile zurückgibt, die der Nutzer eingegeben hat. Schließ das Interface, wenn du fertig bist, sonst wartet das Programm weiter auf Eingaben.

question() hat seinen Prompt ausgegeben, auf eine Eingabezeile gewartet und sie ohne Zeilenumbruch zurückgegeben, deshalb hat das Programm Next year you will be 37. ausgegeben. Für mehrere Fragen wartest du mit await auf ein question() nach dem anderen.

readline question() mit Callback

Die ursprüngliche API, in jeder Node.js-Version, übergibt die Antwort an einen Callback. Verschachtelte Fragen verschachteln Callbacks:

Es hat den Prompt ausgegeben, dann You picked blue. Die Antwort ist ein einfacher String, trimm sie also vor dem Vergleichen: Ein Nutzer, der nach dem Wort ein Leerzeichen tippt, bekommt sonst 'blue ', und das ist nicht gleich 'blue'.

Eingaben zeilenweise lesen

Um jede Zeile zu verarbeiten, bis die Eingabe endet, durchläufst du das Interface mit for await. So liest ein Programm eine Liste, die der Nutzer eintippt (beendet mit Ctrl+D), oder eine Datei, die mit node index.js < numbers.txt hineingepipt wird. Älterer Code macht dasselbe mit Events, rl.on('line', fn) für jede Zeile und rl.on('close', fn) am Ende; die Schleife ist dieses Event-Paar von oben nach unten geschrieben:

Es hat 3 numbers, total 49 ausgegeben, und die Schleife hat von selbst aufgehört, als die Eingabe endete, ein close() ist also nicht nötig. Füg eine vierte Eingabezeile hinzu, 1, und das Ergebnis wird zu 4 numbers, total 50.

Die ganze Standardeingabe auf einmal lesen

Für Eingaben, die aus einem anderen Programm kommen (cat data.txt | node index.js), ist es einfacher, alles mit einem Aufruf zu lesen. File Descriptor 0 ist die Standardeingabe. Eine unter Windows gespeicherte Datei kann Zeilen mit \r\n beenden, teil also an /\r?\n/, wenn die Eingabe von dort kommen kann:

Es hat die drei Artikel in einer Spalte ausgegeben. readFileSync(0) blockiert, bis die Eingabe vollständig ist, was für ein Skript, das eine Pipe liest, und für Tests in Ordnung ist, aber falsch für ein interaktives Tool, bei dem der Nutzer alles tippen müsste, bevor er überhaupt einen Prompt sieht.

Was du wann nimmst

Alle vier lesen dieselbe Standardeingabe. Sie unterscheiden sich darin, wann dein Code den Text bekommt: eine Antwort nach der anderen, eine Zeile nach der anderen oder alles am Ende.

BedarfNimm
Ein paar Fragen der Reihe nach stellenreadline/promises mit await rl.question()
Node.js-Versionen vor 17 unterstützenreadline mit einem question()-Callback
Jede Zeile verarbeiten, sobald sie ankommtfor await (const line of rl)
Eine ganze Pipe oder Datei aus stdin lesenfs.readFileSync(0, 'utf8')
Werte, die vor dem Programmstart feststehenStattdessen process.argv

Häufige Fehler

rl.close() vergessen. Das Interface hält die Standardeingabe offen, deshalb beendet sich das Programm nach der letzten Frage nie. Schließ es, sobald du jede Antwort hast.

Die Antwort als Zahl verwenden. Wie alles, was in einem Terminal getippt wird, ist die Antwort ein String. '36' + 1 ist '361'; wandle zuerst mit Number() um.

Mehrere Antworten in mehrere Fragen pipen. Wenn die Eingabe aus einer Pipe statt von einer Tastatur kommt, liest readline alles auf einmal, und eine Zeile, die ankommt, bevor ihr question() gestellt wird, geht verloren. Für gepipte Eingaben nimm die for await-Schleife oder readFileSync(0).

Die Option output weglassen. Ohne output: process.stdout gibt question() seinen Prompt nie aus, und der Nutzer starrt auf ein leeres Terminal. Die zeilenweise Schleife braucht sie nicht, weil sie nichts ausgibt.

Häufig gestellte Fragen

Warum ist prompt in Node.js nicht definiert?

prompt() ist eine Browserfunktion, die einen Dialog öffnet, und Node.js hat kein Fenster, in dem sie ihn öffnen könnte. Nimm in Node.js readline oder ein Paket wie prompts oder inquirer für Menüs und Passwortfelder.

Wie lese ich ein Passwort, ohne es anzuzeigen?

readline zeigt jede Taste an. Pakete wie prompts oder @inquirer/password maskieren die Eingabe; selbst gemacht heißt das, das Terminal mit process.stdin.setRawMode(true) in den Raw-Modus zu schalten und jede Taste selbst zu behandeln.

Soll ich readline oder process.argv nehmen?

Nimm process.argv, wenn die Werte vor dem Programmstart feststehen, damit es in einem Skript ohne Person davor laufen kann. Nimm readline für interaktive Tools, die eine Frage nach der anderen stellen.

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

Los geht's