Чтобы прочитать ввод пользователя в Node.js, создайте интерфейс readline на process.stdin и спросите через rl.question(). В Node.js нет prompt(): браузерная версия открывает диалог, а у терминальной программы его нет. Современный вариант использует readline/promises, где await rl.question('Name? ') возвращает строку, которую ввёл пользователь. Закройте интерфейс, когда закончите, иначе программа так и будет ждать ввода.
question() вывел свой вопрос, дождался одной строки ввода и вернул её без перевода строки, так что программа вывела Next year you will be 37. Для нескольких вопросов дожидайтесь одного question() за другим.
readline question() с callback
Исходный API, который есть в любой версии Node.js, передаёт ответ в callback. Вложенные вопросы означают вложенные callback:
Программа вывела вопрос, затем You picked blue. Ответ это обычная строка, поэтому делайте trim перед сравнением: иначе пользователь, который поставил пробел после слова, получит 'blue ', а это не равно 'blue'.
Чтение по строкам
Чтобы обработать каждую строку до конца ввода, обходите интерфейс через for await. Так программа читает список, который ввёл пользователь (конец по Ctrl+D), или файл, переданный через node index.js < numbers.txt. Старый код делает то же через события: rl.on('line', fn) на каждую строку и rl.on('close', fn) в конце; цикл это та же пара событий, записанная сверху вниз:
Программа вывела 3 numbers, total 49, а цикл закончился сам, когда закончился ввод, поэтому close() не нужен. Добавьте четвёртую строку ввода, 1, и результат станет 4 numbers, total 50.
Прочитать весь stdin сразу
Для ввода из другой программы через пайп (cat data.txt | node index.js) проще прочитать всё одним вызовом. Файловый дескриптор 0 это стандартный ввод. Файл, сохранённый в Windows, может заканчивать строки на \r\n, поэтому делите по /\r?\n/, если ввод может прийти оттуда:
Программа вывела три товара в столбик. readFileSync(0) блокирует выполнение, пока ввод не закончится. Для скрипта, который читает пайп, и для тестов это нормально, а для интерактивного инструмента нет: пользователь ввёл бы всё до того, как увидел хоть один вопрос.
Что выбрать
Все четыре способа читают один и тот же стандартный ввод. Разница в том, когда ваш код получает текст: по одному ответу, по одной строке или всё в конце.
| Задача | Что использовать |
|---|---|
| Задать несколько вопросов по порядку | readline/promises с await rl.question() |
| Поддержать версии Node.js до 17 | readline с callback в question() |
| Обрабатывать каждую строку по мере поступления | for await (const line of rl) |
| Прочитать весь пайп или файл из stdin | fs.readFileSync(0, 'utf8') |
| Значения известны до запуска программы | Вместо этого process.argv |
Частые ошибки
Забыли rl.close(). Интерфейс держит стандартный ввод открытым, и программа не завершается после последнего вопроса. Закройте его, когда получите все ответы.
Ответ используют как число. Как и всё, что вводится в терминале, ответ это строка. '36' + 1 равно '361'; сначала преобразуйте через Number().
Несколько ответов через пайп на несколько вопросов. Когда ввод приходит из пайпа, а не с клавиатуры, readline читает его весь сразу, и строка, пришедшая до того, как задан её question(), теряется. Для ввода из пайпа используйте цикл for await или readFileSync(0).
Пропущена опция output. Без output: process.stdout question() не выводит вопрос, и пользователь смотрит на пустой терминал. Циклу по строкам она не нужна, потому что он ничего не выводит.
Часто задаваемые вопросы
Почему в Node.js prompt is not defined?
prompt() это функция браузера, которая открывает диалог, а у Node.js нет окна, где его открыть. В Node.js используйте readline или пакет вроде prompts или inquirer для меню и полей пароля.
Как прочитать пароль, не показывая его?
readline отображает каждую нажатую клавишу. Пакеты вроде prompts или @inquirer/password скрывают ввод; если делать это самому, придётся перевести терминал в raw режим через process.stdin.setRawMode(true) и обрабатывать каждую клавишу.
readline или process.argv?
Используйте process.argv, когда значения известны до запуска программы, чтобы она могла работать в скрипте без человека. Используйте readline для интерактивных инструментов, которые задают вопросы один за другим.