Żeby odczytać dane od użytkownika w Node.js, utwórz interfejs readline na process.stdin i pytaj przez rl.question(). Node.js nie ma prompt(): wersja z przeglądarki otwiera okno dialogowe, a program w terminalu go nie ma. Nowoczesna forma używa readline/promises, gdzie await rl.question('Name? ') zwraca linię wpisaną przez użytkownika. Zamknij interfejs, gdy skończysz, bo inaczej program dalej czeka na dane.
question() wypisało swoje pytanie, poczekało na jedną linię wejścia i zwróciło ją bez znaku nowej linii, więc program wypisał Next year you will be 37. Przy kilku pytaniach czekaj przez await na jedno question() po drugim.
readline question() z callbackiem
Pierwotne API, dostępne w każdej wersji Node.js, przekazuje odpowiedź do callbacku. Zagnieżdżone pytania zagnieżdżają callbacki:
Wypisało pytanie, a potem You picked blue. Odpowiedź to zwykły string, więc przed porównaniem zrób trim: użytkownik, który wpisze spację po słowie, inaczej dostanie 'blue ', a to nie jest równe 'blue'.
Czytanie wejścia linia po linii
Żeby przetworzyć każdą linię aż do końca wejścia, przejdź po interfejsie pętlą for await. Tak program czyta listę wpisywaną przez użytkownika (zakończoną przez Ctrl+D) albo plik przekazany potokiem przez node index.js < numbers.txt. Starszy kod robi to samo przez zdarzenia, rl.on('line', fn) dla każdej linii i rl.on('close', fn) na końcu; pętla to ta para zdarzeń zapisana z góry na dół:
Wypisało 3 numbers, total 49, a pętla sama się skończyła, gdy skończyło się wejście, więc close() nie jest potrzebne. Dodaj czwartą linię wejścia, 1, a wynik zmieni się na 4 numbers, total 50.
Odczyt całego stdin naraz
Przy wejściu przekazanym potokiem z innego programu (cat data.txt | node index.js) prościej jest wczytać wszystko jednym wywołaniem. Deskryptor pliku 0 to standardowe wejście. Plik zapisany w Windows może kończyć linie przez \r\n, więc dziel po /\r?\n/, gdy wejście może stamtąd pochodzić:
Wypisało trzy produkty w kolumnie. readFileSync(0) blokuje, dopóki wejście nie jest kompletne, co jest w porządku dla skryptu czytającego potok i dla testów, ale źle sprawdza się w narzędziu interaktywnym, gdzie użytkownik musiałby wpisać wszystko, zanim zobaczy jakiekolwiek pytanie.
Którego użyć
Wszystkie cztery czytają to samo standardowe wejście. Różnią się tym, kiedy twój kod dostaje tekst: po jednej odpowiedzi, po jednej linii albo wszystko na końcu.
| Potrzeba | Użyj |
|---|---|
| Zadać kilka pytań po kolei | readline/promises z await rl.question() |
| Obsłużyć wersje Node.js sprzed 17 | readline z callbackiem question() |
| Obsłużyć każdą linię, gdy tylko przyjdzie | for await (const line of rl) |
| Wczytać cały potok albo plik ze stdin | fs.readFileSync(0, 'utf8') |
| Wartości znane przed startem programu | Zamiast tego process.argv |
Częste błędy
Zapominanie o rl.close(). Interfejs trzyma standardowe wejście otwarte, więc program po ostatnim pytaniu nigdy się nie kończy. Zamknij go, gdy masz wszystkie odpowiedzi.
Używanie odpowiedzi jako liczby. Jak wszystko wpisane w terminalu, odpowiedź to string. '36' + 1 to '361'; najpierw zamień przez Number().
Przekazywanie kilku odpowiedzi potokiem do kilku pytań. Gdy wejście przychodzi z potoku zamiast z klawiatury, readline czyta wszystko naraz, a linia, która przyjdzie przed zadaniem jej question(), przepada. Przy wejściu z potoku użyj pętli for await albo readFileSync(0).
Pomijanie opcji output. Bez output: process.stdout question() nigdy nie wypisze pytania, a użytkownik patrzy w pusty terminal. Pętla linia po linii jej nie potrzebuje, bo nic nie wypisuje.
Najczęściej zadawane pytania
Dlaczego prompt nie jest zdefiniowany w Node.js?
prompt() to funkcja przeglądarki, która otwiera okno dialogowe, a Node.js nie ma okna, w którym mógłby je otworzyć. W Node.js użyj readline albo pakietu takiego jak prompts lub inquirer do menu i pól na hasło.
Jak odczytać hasło bez wyświetlania go?
readline wyświetla każdy wciśnięty klawisz. Pakiety takie jak prompts albo @inquirer/password maskują wpisywany tekst; zrobienie tego samemu oznacza przełączenie terminala w tryb raw przez process.stdin.setRawMode(true) i obsługę każdego klawisza.
readline czy process.argv?
Użyj process.argv, gdy wartości są znane przed startem programu, żeby mógł działać w skrypcie bez człowieka przy klawiaturze. Użyj readline w narzędziach interaktywnych, które zadają pytania jedno po drugim.