как запустить js скрипт в node js

Как запустить JavaScript с помощью Node.js

как запустить js скрипт в node js

Если вы только сели за изучение JavaScript, то у вас очень быстро возникнет вопрос: а как запустить код?

Простой скрипт можно запустить прямо в браузере. Большинство из них сегодня позволяют сделать это в пару кликов. Но возможностей браузера не хватит, если задача — разработка сложного приложения, работающего с базами данных и файлами. Здесь на помощь приходит Node.js.

Node.js — среда выполнения JavaScript-кода. Она создана на базе движка V8, который крутится в сердце браузера Chrome. Эта среда позволяет запускать JavaScript-сценарии в окружении операционной системы, а не браузера.

Кроме стандартных возможностей JavaScript, Node.js даёт инструменты для работы с сетью, вводом и выводом, файловой системой и не только. В придачу к среде идёт и пакетный менеджер npm, который позволяет разработчикам ставить сторонние пакеты в одну строку.

Разобраться с базовыми функциями будет просто, если вы уже знаете JavaScript или другой скриптовый язык.

Давайте попробуем

Сначала установим среду с сайта разработчиков и проверим в консоли, что всё прошло нормально.

Введём простую команду:

Результат, который мы получили:

Рассмотрим пару простых примеров. По традиции выведем Hello world! :

как запустить js скрипт в node jsHello world!

Попробуем пример сложнее, например, цикл выводов. Как консоль отреагирует на него?

как запустить js скрипт в node jsЦикл выводов.

Node.js отлично справляется и с более сложными конструкциями, даже самостоятельно выстраивая лесенку. В случае обнаружения ошибки, он тут же сообщит об этом, остановив скрипт.

Например, случайно пропустим букву в команде:

как запустить js скрипт в node jsУпс, ошибка.

Ну вот, всё необходимое для написания простых и компактных приложений есть. Но писать большое приложение на десятки строк кода в консоли будет не слишком-то удобно. Да и такой подход не сработает, если приложение разбито на несколько скриптов, лежащих в разных файлах.

Усложняем задачу

Попробуем перейти к чуть более продвинутому использованию среды.

Создайте на жёстком диске папку для проекта и положите туда ваш готовый скрипт. Назовите его index.js — так принято. Если под рукой скрипта нет, то возьмите цикл с выводом простого значения, с которого мы начали.

Второй способ — самостоятельно создать текстовый файл, назвать его package.json и заполнить все необходимые поля. Файл будет представлением приложения, в котором содержится его имя, версия, авторы и зависимости. На данном этапе может выглядеть так:

Но вводить команду постоянно — не слишком рациональное расходование времени. Давайте упростим себе жизнь.

Скопируйте в файл следующий код:

Подробнее про команды можно прочитать здесь.

Что мы сделали

Теперь при вводе команды npm start будет запускаться наш сервер, который будет обрабатывать всё содержимое нашего приложения.

Источник

Начало работы с Node.js

Node Hero: Глава 1

как запустить js скрипт в node js

как запустить js скрипт в node js

Мы начнем с основ: никаких предварительных знаний Node.js не требуется. Цель этой книги — начать работу с Node.js и убедиться, что вы понимаете, как писать приложение с использованием этой платформы.

В первой главе вы узнаете, что такое Node.js, как установить её на свой компьютер и как начать с ней работать — так что в следующих главах можно будет приступить к реальной разработке. Приступим!

Node.js в двух словах

Node.js — это среда выполнения JavaScript, построенная на JavaScript-движке V8 из Chrome. В основе Node.js лежит событийно-управляемая модель с неблокирующими операциями I/O, что делает её легкой и эффективной.

Другими словами: Node.js предлагает вам возможность писать невероятно производительный серверный код с использованием JavaScript. Как говорится в официальном описании: Node.js — это среда выполнения, использующая тот же JavaScript-движок V8, который вы можете найти в браузере Google Chrome. Но этого недостаточно для успеха Node.js. В Node.js используется libuv — кросс-платформенная библиотека поддержки с акцентом на асинхронный ввод-вывод.

С точки зрения разработчика, Node.js однопоточна, но под капотом libuv использует треды, события файловой системы, реализует цикл событий, включает в себя тред-пулинг и так далее. В большинстве случаев вы не будете взаимодействовать с libuv напрямую.

Установка Node.js для старта

Последнюю версию Node.js вы можете найти на официальном сайте: https://nodejs.org/en/download/.

При таком подходе довольно легко начать работу, но если позже вы захотите добавить в систему больше версий Node.js, лучше начать использовать nvm ( node version manager) — диспетчер версий Node.js.

После его установки вы сможете использовать очень простой CLI API для смены версии Node.js:

Установка различных версий Node.js

Затем, если вы хотите проверить в работе экспериментальную версию:

Чтобы убедиться, что у вас установлена и запущена Node.js, выполните:

Если все в порядке, эта команда вернет номер версии текущего активного бинарного файла Node.js.

Использование нескольких версий Node.js

Если вы работаете над проектом, поддерживающим Node.js v4, вы можете начать использовать эту версию с помощью следующей команды:

Затем вы можете переключиться на Node.js v5 с помощью той же самой команды:

Хорошо, теперь мы знаем, как устанавливать Node.js и переключаться между её версиями, но в чём смысл?

С тех пор как был сформирован Node.js Foundation, Node.js имеет план релизов. Это очень похоже на другие проекты Linux Foundation. Это означает, что есть два релиза: стабильный и экспериментальный. В Node.js стабильными версиями с долговременной поддержкой (LTS) являются те, которые начинаются с четных чисел (4, 6, 8, …). Экспериментальные версии нумеруются нечетными числами (5, 7, …).

Мы рекомендуем использовать версию LTS в продакшене и пробовать новые возможности с экспериментальной версией.

Hello World

Чтобы начать работу с Node.js, давайте попробуем её в консоли! Запустите Node.js, просто набрав node :

Хорошо, давайте попробуем что-то напечатать:

После нажатия Enter вы получите следующее:

Не стесняйтесь играть с Node.js с помощью этого интерфейса: я обычно тестирую небольшие фрагменты кода здесь, если я не хочу помещать их в файл.

Пришло время создать наше приложение Hello Node.js!

Модульность для вашего приложения

В следующей главе под названием «Использование NPM» мы рассмотрим, как использовать NPM — менеджер пакетов для JavaScript.

Источник

Как написать и запустить свою первую программу на Node.js

Node.js – это популярная открытая среда выполнения, которая может запускать JavaScript вне браузера при помощи механизма V8. Механизм V8 используется для обработки JavaScript в браузере Google Chrome. Среда Node обычно используется для разработки инструментов командной строки и веб-серверов.

Умея работать в Node.js, вы сможете писать код для фронтенда и бэкенда на одном языке. Так будет проще переключаться между контекстами. Кроме того, вы сможете использовать одни и те же библиотеки на фронтенде и бэкенде.

Благодаря поддержке асинхронного выполнения Node.js отлично справляется с задачами с высокой нагрузкой I/O, потому он отлично подходит для веб-разработки. Приложения реального времени (например, видео-стримы или приложения, которые непрерывно отправляют и получают данные) могут работать более эффективно, если написать их в Node.js.

В этом мануале вы узнаете, как написать свою первую программу в среде выполнения Node.js. Вы познакомитесь с некоторыми концепциями, специфичными для Node. Мы создадим программу, которая поможет пользователям проверять переменные среды в своей системе. Для этого мы научимся выводить строки на консоль, собирать пользовательский ввод и получать доступ к переменным среды.

Требования

1: Вывод на консоль

Чтобы создать простейшую программу “Hello, World!”, откройте текстовый редактор (например, nano) и создайте новый файл:

В файл введите следующий код:

Объект console в Node.js предоставляет простые методы для записи в stdout, stderr или в любой другой поток Node.js (что в большинстве случаев является командной строкой). Метод log выводит в поток stdout, так что вы можете увидеть его в своей консоли.

В контексте Node.js потоки – это объекты, которые могут принимать (например поток stdout) или выводить данные (например сетевой сокет или файл). В случае потоков stdout и stderr любые отправленные им данные будут показаны в консоли. Одна из замечательных особенностей потоков заключается в том, что они легко перенаправляются, и вы можете, например, просто перенаправить вывод своей программы в файл.

Сохраните и закройте nano, нажав сочетание клавиш CTRL + X, при появлении запроса на сохранение файла нажмите Y. Теперь ваша программа готова к запуску.

2: Запуск программы

Чтобы запустить свою новую программу, используйте такую команду:

Программа hello.js запустится и выведет такой результат:

Интерпретатор Node.js прочитал файл и выполнил строку:

вызвав метод log глобального объекта console. Строка “Hello World” была передана в качестве аргумента функции log.

Кавычки необходимы в коде, чтобы определить границы строки, но в результате они не выводятся на экран.

Убедившись, что программа работает, мы можем сделать ее более интерактивной.

3: Получение пользовательского ввода с помощью аргументов командной строки

Каждый раз, когда вы запускаете программу Node.js «Hello, World!», она выдает один и тот же результат. Чтобы сделать программу более динамичной, давайте научим ее собирать информацию от пользователя и отображать ее на экране.

Инструменты командной строки обычно принимают различные аргументы, которые изменяют их поведение. Например, команда node с аргументом –version печатает установленную версию, а не запускает интерпретатор. На этом этапе мы научим код принимать пользовательский ввод с помощью аргументов командной строки.

Создайте новый файл arguments.js в nano:

Введите следующую строку:

Объект process – это глобальный объект Node.js, который содержит функции и данные, связанные с текущим запущенным процессом Node.js. Свойство argv – это массив строк, содержащий все аргументы командной строки, заданные программе.

Сохраните и закройте файл.

Теперь при запуске программы можно использовать аргументы:

node arguments.js hello world

Вы получите такой вывод:

[ ‘/usr/bin/node’,
‘/home/8host/first-program/arguments.js’,
‘hello’,
‘world’ ]

Первым аргументом в массиве process.argv всегда является местоположение двоичного файла Node.js, с помощью которого выполняется программа. Второй аргумент – это всегда местоположение запускаемого файла. Остальные аргументы – это то, что ввел пользователь, в данном случае hello и world.

Нас больше всего интересуют не те аргументы, которые по умолчанию предоставляет Node.js, а аргументы, введенные пользователем. Откройте файл arguments.js в редакторе:

Измените console.log (process.arg); таким образом:

Поскольку argv является массивом, вы можете использовать встроенный в JavaScript метод slice, который возвращает набор элементов. Используя функцию slice с аргументом 2, вы получаете все элементы argv, которые идут в массиве после второго элемента, то есть аргументы, введенные пользователем.

Перезапустите программу с помощью команды node и тех же аргументов, что и в прошлый раз:

node arguments.js hello world

Теперь вывод выглядит так:

Итак, программа может собирать пользовательские данные, давайте теперь научимся собирать данные из среды программы.

4: Доступ к переменным среды

Переменные среды – это данные типа «ключ-значение», хранящиеся вне программы и предоставляемые операционной системой. Как правило, они устанавливаются системой или пользователем и доступны всем запущенным процессам для конфигурации или определения состояния. Вы можете использовать объект process, чтобы получить доступ к переменным среды.

Используйте nano для создания нового файла environment.js:

Добавьте следующий код:

Объект env хранит все переменные среды, которые доступны, когда Node.js запускает программу.

Сохраните и закройте файл, а затем запустите файл environment.js с помощью команды node.

После запуска программы вы должны увидеть подобный вывод:


COLORTERM: ‘truecolor’,
SSH_AUTH_SOCK: ‘/run/user/1000/keyring/ssh’,
XMODIFIERS: ‘@im=ibus’,
DESKTOP_SESSION: ‘ubuntu’,
SSH_AGENT_PID: ‘1150’,
PWD: ‘/home/8host/first-program’,
LOGNAME: ‘8host’,
GPG_AGENT_INFO: ‘/run/user/1000/gnupg/S.gpg-agent:0:1’,
GJS_DEBUG_TOPICS: ‘JS ERROR;JS LOG’,
WINDOWPATH: ‘2’,
HOME: ‘/home/8host’,
USERNAME: ‘8host’,
IM_CONFIG_PHASE: ‘2’,
LANG: ‘en_US.UTF-8’,
VTE_VERSION: ‘5601’,
CLUTTER_IM_MODULE: ‘xim’,
GJS_DEBUG_OUTPUT: ‘stderr’,
LESSCLOSE: ‘/usr/bin/lesspipe %s %s’,
TERM: ‘xterm-256color’,
LESSOPEN: ‘| /usr/bin/lesspipe %s’,
USER: ‘8host’,
DISPLAY: ‘:0’,
SHLVL: ‘1’,
PATH:
‘/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin’,
DBUS_SESSION_BUS_ADDRESS: ‘unix:path=/run/user/1000/bus’,
_: ‘/usr/bin/node’,
OLDPWD: ‘/home/8host’ >

Имейте в виду, что многие переменные среды зависят от конфигурации и настроек вашей системы, и ваши выходные данные могут существенно отличаться от того, что вы видите здесь.

Вместо длинного списка переменных среды вам может потребоваться получить конкретную переменную. Давайте попробуем это сделать.

5: Доступ к конкретной переменной среды

На этом этапе мы научимся просматривать переменные среды с помощью глобального объекта process.env и выводить их значения на консоль.

Объект process.env выполняет простое сопоставление имен переменных среды и их значений, хранящихся в виде строк. Как и с другими объектами в JavaScript, вы получите доступ к отдельному свойству, ссылаясь на его имя в квадратных скобках.

Откройте файл environment.js для редактирования:

Измените console.log (process.env) так:

Сохраните файл и закройте файл. Теперь запустите программу environment.js:

Вывод теперь выглядит так:

Опять же, ваш вывод, вероятно, будет отличаться от того, что вы видите здесь, потому что он специфичен для вашей системы.

Теперь, когда вы можете извлекать конкретные переменные среды, вы можете улучшить свою программу: она может запрашивать у пользователя переменную, которую он хочет получить.

6: Извлечение аргумента в ответ на ввод пользователя

Давайте используем возможность чтения аргументов командной строки и переменных среды для создания утилиты, которая выводит значение переменной среды на экран.

С помощью nano создайте новый файл echo.js:

Добавьте следующий код:

const args = process.argv.slice(2);
console.log(process.env[args[0]]);

В первой строке echo.js в переменной args сохраняются все аргументы командной строки, предоставленные пользователем. Вторая строка отображает переменную среды, хранящуюся в первом элементе args, то есть первый аргумент командной строки, предоставленный пользователем.

Сохраните и закройте файл. Запустите программу:

Аргумент HOME был сохранен в массиве args, который затем использовался для поиска значения в среде через объект process.env.

Теперь вы можете получить доступ к значению любой переменной среды в вашей системе. Чтобы убедиться в этом, попробуйте просмотреть следующие переменные: PWD, USER, PATH.

Получение отдельных переменных – это хорошо, но лучше бы позволить пользователям указывать количество переменных.

7: Просмотр нескольких переменных среды

В настоящее время приложение может выдавать только одну переменную среды за один раз. Было бы полезно научить программу принимать несколько аргументов командной строки и выводить соответствующие значения. Используйте nano, чтобы отредактировать echo.js:

Отредактируйте файл так:

const args = process.argv.slice(2);
args.forEach(arg => < console.log(process.env[arg]); >);

Метод forEach – это стандартный метод JavaScript для всех объектов массива. Он принимает функцию обратного вызова, которая используется при выполнении итерации по каждому элементу массива. Мы используем forEach для массива args, предоставляя ему функцию обратного вызова, которая выводит значение текущего аргумента в среде.

Сохраните и закройте файл. Теперь перезапустите программу с двумя аргументами:

node echo.js HOME PWD

Вы должны увидеть следующий вывод:

Функция forEach обеспечивает вывод каждого аргумента командной строки в массиве args.

Теперь программа может извлекать переменные, которые запрашивает пользователь. Осталось только разобраться с неверным пользовательским вводом.

8: Обработка неправильного пользовательского ввода

Попробуйте передать программе неправильный аргумент:

node echo.js HOME PWD NOT_DEFINED

Вывод будет выглядеть примерно так:

/home/8host
/home/8host/first-program
undefined

Первые две строки правильные, а последняя строка имеет значение undefined. В JavaScript неопределенное значение undefined означает, что переменной или свойству не было присвоено значение. Поскольку NOT_DEFINED не является допустимой переменной среды, ее значение отображается как undefined.

Лучше вместо этого показать пользователю сообщение об ошибке, если аргумент командной строки не найден в среде.

Отредактируйте код echo.js таким образом:

const args = process.argv.slice(2);
args.forEach(arg => <
let envVar = process.env[arg];
if (envVar === undefined) < console.error(`Could not find «$» in environment`);

> else < console.log(envVar); >
>);

Мы изменили функцию обратного вызова для forEach, и теперь она делает следующие вещи:

Примечание: Функция console.error выводит сообщение на экран через поток stderr, а console.log – через поток stdout. Когда вы запускаете эту программу через командную строку, вы не видите разницы между потоками stdout и stderr. Однако ошибки рекомендуется выводить через поток stderr, чтобы их было легче идентифицировать и обрабатывать другими программами, которые чувствуют эту разницу.

Теперь выполните следующую команду еще раз:

node echo.js HOME PWD NOT_DEFINED

На этот раз получится:

/home/8host
/home/8host/first-program
Could not find «NOT_DEFINED» in environment

Теперь, когда программа получает аргумент командной строки, который не соответствует ни одной переменной, она выводит четкое сообщение об ошибке.

Заключение

Начав с простой программы «Hello World», вы написали утилиту командной строки Node.js, которая считывает пользовательские аргументы и выводит переменные среды.

Если вы хотите продолжить работу, вы можете еще больше изменить поведение этой программы. Например, можно проверить аргументы командной строки перед выводом результатов. Если один из аргументов не определяется, вы можете вернуть ошибку, и пользователь получит вывод, только если все аргументы будут соответствовать переменным среды.

Источник

Как запустить js-file в консоле Node.js?

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Как запустить функцию node.js?
Попал мне в руки бот на nodejs, он запускается все в порядке, в нем есть функция загрузки.

как запустить js скрипт в node jsКак запустить Node сервер в фоне
Подскажите пожалуй сто, как(то есть какими консольными командами) запустить приложение node в.

как запустить js скрипт в node jsКак запустить чат программу на node.js
папка лежит на диске С. И что дальше делать,чтоб программа заработала? можно подробнее каждый шаг.

KingR, эти команды нужно запускать не в нодовском REPL (не в консоли Node), а в консоли системы. Ну и соответственно, js-файл при этом должен находиться в текущей рабочей директории, в противном случае нужно указывать полный путь до него.

К слову, символ «$» тоже вводить не нужно, это типичное приглашение (prompt) оболочки.

Помощь в написании контрольных, курсовых и дипломных работ здесь.

как запустить js скрипт в node jsКак запустить make-file по имени?
Как запустить make-file по имени?

как можно запустить wave file вместе с загрузкой формы?
как можно запустить wave file вместе с загрузкой формы? есть ли исходник?

как запустить js скрипт в node jsЗапустить скрипт на node на хостинге
Подскажите,пожалуйста,как запустить скрипт на node на хостинге. Понял так. При написании.

Источник

Выразительный JavaScript: Node.js

Содержание

Ученик спросил: «Программисты встарь использовали только простые компьютеры и программировали без языков, но они делали прекрасные программы. Почему мы используем сложные компьютеры и языки программирования?». Фу-Тзу ответил: «Строители встарь использовали только палки и глину, но они делали прекрасные хижины».

Мастер Юан-Ма, «Книга программирования»

На текущий момент вы учили язык JavaScript и использовали его в единственном окружении: в браузере. В этой и следующей главе мы кратко представим вам Node.js, программу, которая позволяет применять навыки JavaScript вне браузера. С ней вы можете написать всё, от утилит командной строки до динамических HTTP серверов.

Эти главы посвящены обучению важным идеям, составляющим Node.js и предназначены для передачи вам достаточного количества информации, чтобы вы могли писать полезные программы в этой среде. Они не пытаются быть всеобъемлющими справочниками по Node.

Код из предыдущих глав вы могли писать и исполнять прямо в браузере, но код из этой главы написан для Node и в браузере работать не будет.

Если вы хотите сразу запускать код из этой главы, начните с установки Node с сайта nodejs.org для вашей операционки. Также на этом сайте вы найдёте документацию по Node и его встроенным модулям.

Вступление

Одна из наиболее сложных проблем при написании систем, общающихся по сети – обработка ввода и вывода. Чтение и запись данных в сеть и из сети, на диск, и другие устройства. Перемещение данных требует времени, и грамотное планирование этих действий может сильно повлиять на время отклика системы для пользователя или сетевых запросов.

В традиционном методе обработки ввода и вывода принято, что функция, к примеру, readFile, начинает читать файл и прекращает работать только когда файл полностью прочитан. Это называется синхронным вводом-выводом (synchronous I/O, input/output).

Node был задуман с целью облегчить и упростить использование асинхронного I/O. Мы уже встречались с асинхронными интерфейсами, такими, как объект браузера XMLHttpRequest, обсуждавшийся в главе 17. Такой интерфейс позволяет скрипту продолжать работу, пока интерфейс делает свою, и вызывает функцию обратного вызова по окончанию работы. Таким образом в Node работает весь I/O.

JavaScript легко вписывается в систему типа Node. Это один из немногих языков, в которые не встроена система I/O. Поэтому JavaScript легко встраивается в довольно эксцентричный подход к I/O в Node и в результате не порождает две разных системы ввода и вывода. В 2009 году при разработке Node люди уже использовали I/O в браузере, основанный на обратных вызовах, поэтому сообщество вокруг языка было привычно к асинхронному стилю программирования.

Асинхронность

Попробую проиллюстрировать разницу в синхронном и асинхронном подходах в I/O на небольшом примере, где программа должна получить два ресурса из интернета, и затем сделать что-то с данными.

В синхронном окружении очевидным способом решения задачи будет сделать запросы последовательно. У этого метода есть минус – второй запрос начнётся только после окончания первого. Общее время будет не меньше, чем сумма времени на обработку двух запросов. Это неэффективное использование компьютера, который большую часть времени будет простаивать, пока происходит передача данных по сети.

Решение проблемы в синхронной системе – запуск дополнительных потоков контроля исполнения программы (в главе 14 мы их уже обсуждали). Второй поток может запустить второй запрос, и затем оба потока будут ждать возврата результата, после чего они заново будут синхронизированы для сведения работы в один результат.

На диаграмме жирные линии обозначают время нормальной работы программы, а тонкие – время ожидания I/O. В синхронной модели время, затраченное на I/O, входит во временной график каждого из потоков. В асинхронной, запуск действия по I/O приводит к разветвлению временной линии. Поток, запустивший I/O, продолжает выполнение, а I/O выполняется параллельно ему, по окончанию работы делая обратный вызов функции.

как запустить js скрипт в node js
Поток выполнения программы для синхронного и асинхронного I/O

Ещё один способ выразить эту разницу: в синхронной модели ожидание окончания I/O неявное, а в асинхронной – явное, и находится под нашим непосредственным контролем. Но асинхронность работает в обе стороны. С её помощью выражать программы, не работающие по принципу прямой линии, проще, но выражать прямолинейные программы становится сложнее.

В главе 17 я уже касался того факта, что обратные вызовы привносят кучу шума и делают программу менее упорядоченной. Является ли такой подход в общем хорошей идеей – спорный вопрос. В любом случае, требуется время, чтобы привыкнуть к нему.

Но для системы, основанной на JavaScript, я бы сказал, что использование асинхронности с обратными вызовами имеет смысл. Одна из сильных сторон JavaScript – простота, и попытки добавить в программу несколько потоков привели бы к сильному усложнению. Хотя обратные вызовы не делают код простым, их идея очень проста и в то же время достаточно сильна для того, чтобы писать высокопроизводительные веб-серверы.

Команда node

Когда в вашей системе установлен Node.js, у вас появляется программа под названием node, которая запускает файлы JavaScript. Допустим, у вас есть файл hello.js со следующим кодом:

Вы можете выполнить свою программу из командной строки:

Метод console.log в Node действует так же, как в браузере. Выводит кусок текста. Но в Node текст выводится на стандартный вывод, а не в консоль JavaScript в браузере.

Если запустить node без файла, он выдаст вам строку запроса, в которой можно писать код на JavaScript и получать результат.

Переменная process, так же как и console, доступна в Node глобально. Она обеспечивает несколько способов для инспектирования и манипулирования программой. Метод exit заканчивает процесс, и ему можно передать код статуса окончания программы, который сообщает программе, запустившей node (в данном случае, программной оболочке), завершилась ли программа удачно (нулевой код) или с ошибкой (любое другое число).

Для доступа к аргументам командной строки, переданным программе, можно читать массив строк process.argv. В него также включены имя команды node и имя вашего скрипта, поэтому список аргументов начинается с индекса 2. Если файл showargv.js содержит только инструкцию console.log(process.argv), его можно запустить так:

Все стандартные глобальные переменные JavaScript — Array, Math, JSON, также есть в окружении Node. Но там отсутствует функционал, связанный с работой браузера, например document или alert.

Объект глобальной области видимости, который в браузере называется window, в Node имеет более осмысленное название global.

Модули

Кроме нескольких упомянутых переменных, вроде console и process, Node держит мало функционала в глобальной области видимости. Для доступа к остальным встроенным возможностям вам надо обращаться к системе модулей.

Система CommonJS, основанная на функции require, была описана в главе 10. Такая система встроена в Node и используется для загрузки всего, от встроенных модулей и скачанных библиотек до файлов, являющихся частями вашей программы.

Когда передаётся строка, которая не выглядит как относительный или абсолютный путь, то предполагается, что это либо встроенный модуль, или модуль, установленный в директории node_modules. К примеру, require(«fs») выдаст вам встроенный модуль для работы с файловой системой, а require(«elife») попробует загрузить библиотеку из node_modules/elife/. Типичный метод установки библиотек – при помощи NPM, к которому я вернусь позже.

Для демонстрации давайте сделаем простой проект из двух файлов. Первый назовём main.js, и в нём будет определён скрипт, вызываемый из командной строки, предназначенный для искажения строк.

Файл garble.js определяет библиотеку искажения строк, которая может использоваться как заданной ранее программой для командной строки, так и другими скриптами, которым нужен прямой доступ к функции garble.

Замена module.exports вместо добавления к нему свойств позволяет нам экспортировать определённое значение из модуля. В данном случае, результатом запроса нашего модуля получится сама функция искажения.

Функция разбивает строку на символы, используя split с пустой строкой, и затем заменяет все символы на другие, чьи коды на 5 единиц больше. Затем она соединяет результат обратно в строку.

Теперь мы можем вызвать наш инструмент:

Установка через NPM

NPM, вскользь упомянутый в главе 10, это онлайн-хранилище модулей JavaScript, многие из которых написаны специально для Node. Когда вы ставите Node на компьютер, вы получаете программу npm, которая даёт удобный интерфейс к этому хранилищу.

К примеру, один из модулей NPM зовётся figlet, и он преобразует текст в “ASCII art”, рисунки, составленные из текстовых символов. Вот как его установить:

После запуска npm install NPM создаст директорию node_modules. Внутри неё будет директория figlet, содержащая библиотеку. Когда мы запускаем node и вызываем require(«figlet»), библиотека загружается и мы можем вызвать её метод text, чтобы вывести большие красивые буквы.

Что интересно, вместо простого возврата строки, в которой содержатся большие буквы, figlet.text принимает функцию для обратного вызова, которой он передаёт результат. Также он передаёт туда ещё один аргумент, error, который в случае ошибки будет содержать объект error, а в случае успеха – null.

Такой принцип работы принят в Node. Для создания букв figlet должен прочесть файл с диска, содержащий буквы. Чтение файла – асинхронная операция в Node, поэтому figlet.text не может вернуть результат немедленно. Асинхронность заразительна – любая функция, вызывающая асинхронную, сама становится асинхронной.

NPM – это больше, чем просто npm install. Он читает файлы package.json, содержащие информацию в формате JSON про программу или библиотеку, в частности, от каких библиотек она зависит. Выполнение npm install в директории, содержащей такой файл, автоматически приводит к установке всех зависимостей, и в свою очередь их зависимостей. Также инструмент npm используется для размещения библиотек в онлайновом хранилище NPM, чтобы другие люди могли их находить, скачивать и использовать.

Больше мы не будем углубляться в детали использования NPM. Обращайтесь на npmjs.org за документацией и простым поиском библиотек.

Модуль file system

Один из самых востребованных встроенных модулей Node – модуль “fs”, что означает «файловая система». Модуль обеспечивает функционал для работы с файлами и директориями.

К примеру, есть функция readFile, читающая файл и делающая обратный вызов с содержимым файла.

Второй аргумент readFile задаёт кодировку символов, в которой нужно преобразовывать содержимое файла в строку. Текст можно преобразовать в двоичные данные разными способами, но самым новым из них является UTF-8. Если у вас нет оснований полагать, что в файле содержится текст в другой кодировке, можно смело передавать параметр «utf8». Если вы не задали кодировку, Node выдаст вам данные в двоичной кодировке в виде объекта Buffer, а не строки. Это массивоподобный объект, содержащий байты из файла.

Схожая функция, writeFile, используется для записи файла на диск.

Здесь задавать кодировку не нужно, потому что writeFile полагает, что если ей на запись дали строку, а не объект Buffer, то её надо выводить в виде текста с кодировкой по умолчанию UTF-8.

Модуль “fs” содержит много полезного: функция readdir возвращает список файлов директории в виде массива строк, stat вернёт информацию о файле, rename переименовывает файл, unlink удаляет, и т.п. См. документацию на nodejs.org.

Многие функции “fs” имеют как синхронный, так и асинхронный вариант. К примеру, есть синхронный вариант функции readFile под названием readFileSync.

Синхронные функции использовать проще и полезнее для простых скриптов, где дополнительная скорость асинхронного метода не важна. Но заметьте – на время выполнения синхронного действия ваша программа полностью останавливается. Если ей надо отвечать на ввод пользователя или другим программам по сети, затыки ожидания синхронного I/O приводят к раздражающим задержкам.

Модуль HTTP

Ещё один основной модуль — «http». Он даёт функционал для создания HTTP серверов и HTTP запросов.

Вот всё, что нужно для запуска простейшего HTTP сервера:

Запустив скрипт на своей машины, вы можете направить браузер по адресу localhost:8000/hello, таким образом создав запрос к серверу. Он ответит небольшой HTML-страницей.

Функция, передаваемая как аргумент к createServer, вызывается при каждой попытке соединения с сервером. Переменные request и response – объекты, представляющие входные и выходные данные. Первый содержит информацию по запросу, например свойство url содержит URL запроса.

Чтобы отправить что-то назад, используются методы объекта response. Первый, writeHead, пишет заголовки ответа (см. главу 17). Вы даёте ему код статуса (в этом случае 200 для “OK”) и объект, содержащий значения заголовков. Здесь мы сообщаем клиенту, что он должен ждать документ HTML.

Затем идёт тело ответа (сам документ), отправляемое через response.write. Этот метод можно вызывать несколько раз, если хотите отправлять ответ по кускам, к примеру, передавая потоковые данные по мере их поступления. Наконец, response.end сигнализирует конец ответа.

Вызов server.listen заставляет сервер слушать запросы на порту 8000. Поэтому вам надо в браузере заходить на localhost:8000, а не просто на localhost (где портом по умолчанию будет 80).

Для остановки такого скрипта Node, который не завершается автоматически, потому что ожидает следующих событий (в данном случае, соединений), надо нажать Ctrl-C.

Настоящий веб-сервер делает гораздо больше того, что описано в примере. Он смотрит на метод запроса (свойство method), чтобы понять, какое действие пытается выполнить клиент, и на URL запроса, чтобы понять, на каком ресурсе это действие должно выполняться. Далее вы увидите более продвинутую версию сервера.

Чтобы сделать HTTP-клиент, мы можем использовать функцию модуля “http” request.

Первый аргумент request настраивает запрос, объясняя Node, с каким сервером будем общаться, какой путь будет у запроса, какой метод использовать, и т.д. Второй – функция. которую надо будет вызвать по окончанию запроса. Ей передаётся объект response, в котором содержится вся информация по ответу – к примеру, код статуса.

Как и объект response сервера, объект, возвращаемый request, позволяет передавать данные методом write и заканчивать запрос методом end. В примере не используется write, потому что запросы GET не должны содержать данных в теле.

Для запросов на безопасные URL (HTTPS), Node предлагает модуль https, в котором есть своя функция запроса, схожая с http.request.

Потоки

Мы видели два примера потоков в примерах HTTP – объект response, в который сервер может вести запись, и объект request, который возвращается из http.request

Потоки с возможностью записи – популярная концепция в интерфейсах Node. У всех потоков есть метод write, которому можно передать строку или объект Buffer. Метод end закрывает поток, а при наличии аргумента, выведет перед закрытием кусочек данных. Обоим методам можно задать функцию обратного вызова через дополнительный аргумент, которую они вызовут по окончанию записи или закрытию потока.

Возможно создать поток, показывающий на файл, при помощи функции fs.createWriteStream. Затем можно использовать метод write для записи в файл по кусочкам, а не целиком, как в fs.writeFile.

Потоки с возможностью чтения будут чуть сложнее. Как переменная request, переданная функции для обратного вызова на HTTP-сервер, так и переменная response, переданная на HTTP-клиент, являются потоками с возможностью чтения. (Сервер читает запрос и потом пишет ответы, а клиент сперва пишет запрос и затем читает ответ). Чтение из потока осуществляется через обработчики событий, а не через методы.

У объектов, создающих события в Node, есть метод on, схожий с методом браузера addEventListener. Вы даёте ему имя события и функцию, и он регистрирует эту функцию, чтоб её вызвали сразу, когда произойдёт событие.

У потоков с возможностью чтения есть события «data» и «end». Первое происходит при поступлении данных, второе – по окончанию. Эта модель подходит к потоковым данным, которые можно сразу обработать, даже если получен не весь документ. Файл можно прочесть в виде потока через fs.createReadStream.

Следующий код создаёт сервер, читающий тела запросов и отправляющий их в ответ потоком в виде текста из заглавных букв.

Переменная chunk, передаваемая обработчику данных, будет бинарным Buffer, который можно преобразовать в строку, вызвав его метод toString, который декодирует его из кодировки по умолчанию (UTF-8).

Следующий код, будучи запущенным одновременно с сервером, отправит запрос на сервер и выведет полученный ответ:

Пример пишет в process.stdout (стандартный вывод процесса, являющийся потоком с возможностью записи), а не в console.log. Мы не можем использовать console.log, так как он добавляет лишний перевод строки после каждого куска кода – это здесь не нужно.

Простой файловый сервер

Давайте скомбинируем наши новые знания о серверах HTTP и работе с файловой системой, и наведём мостик между ними: HTTP-сервер, предоставляющий удалённый доступ к файлам. У такого сервера много вариантов использования. Он позволяет веб-приложениям хранить и делиться данными, или может дать группе людей доступ к набору файлов.

Когда мы относимся к файлам, как к ресурсам HTTP, методы GET, PUT и DELETE можно использовать для чтения, записи и удаления файлов. Мы будем интерпретировать путь в запросе как путь к файлу.

Нам не надо открывать доступ ко всей файловой системе, поэтому мы будем интерпретировать эти пути как заданные относительно корневого каталога, и это будет каталог запуска скрипта. Если я запущу сервер из /home/marijn/public/ (или C:\Users\marijn\public\ на Windows), то запрос на /file.txt должен указать на /home/marijn/public/file.txt (или C:\Users\marijn\public\file.txt).

Программу мы будем строить постепенно, используя объект methods для хранения функций, обрабатывающих разные методы HTTP.

Этот код запустит сервер, возвращающий ошибки 405 – этот код используется для обозначения того, что запрошенный метод сервером не поддерживается.

Функция respond передаётся функциям, обрабатывающим разные методы, и работает как обратный вызов для окончания запроса. Она принимает код статуса HTTP, тело, и, возможно, тип содержимого. Если переданное тело – поток с возможностью чтения, у него будет метод pipe, который используется для передачи читаемого потока в записываемый. Если нет – предполагается, что это либо null (тело пустое), или строка, и тогда она передаётся напрямую в метод ответа end.

Чтобы получить путь из URL в запросе, функция urlToPath, используя встроенный модуль Node “url”, разбирает URL. Она принимает имя пути, нечто вроде /file.txt, декодирует, чтобы убрать экранирующие коды %20, и вставляет в начале точку, чтобы получить путь относительно текущего каталога.

Вам кажется, что функция urlToPath небезопасна? Вы правы. Вернёмся к этому вопросу в упражнениях.

Мы устроим метод GET так, чтобы он возвращал список файлов при чтении директории, и содержимое файла при чтении файла.

Вопрос на засыпку – какой тип заголовка Content-Type мы должны возвращать, читая файл. Поскольку в файле может быть всё, что угодно, сервер не может просто вернуть один и тот же тип для всех. Но NPM с этим может помочь. Модуль mime (индикаторы типа содержимого файла вроде text/plain также называются MIME types) знает правильный тип для огромного количества расширений файлов.

Запустив следующую команду npm в директории, где живёт скрипт сервера, вы сможете использовать require(«mime») для запросов к библиотеке типов.

Когда запрошенного файла не существует, правильным кодом ошибки для этого случая будет 404. Мы будем использовать fs.stat для возврата информации по файлу, чтобы выяснить, есть ли такой файл, и не директория ли это.

Поскольку запросы к диску занимают время, fs.stat работает асинхронно. Когда файла не существует, fs.stat передаст объект error со значением «ENOENT» свойства code в функцию обратного вызова. Было бы здорово, если бы Node определил разные типы ошибок для разных ошибок, но такого нет. Вместо этого он выдаёт запутанные коды в стиле Unix.

Все неожиданные ошибки мы будем выдавать с кодом 500, обозначающим, что на сервере проблема – в отличие от кодов, начинающихся на 4, говорящих о проблеме с запросом. В некоторых ситуациях это будет не совсем аккуратно, но для небольшой примерной программы этого будет достаточно.

Объект stats возвращаемый fs.stat, рассказывает нам о файле всё. Например, size – размер файла, mtime – дата модификации. Здесь нам нужно узнать, директория это или обычный файл – это нам сообщит метод isDirectory.

Для чтения списка файлов в директории мы используем fs.readdir, и через ещё один обратный вызов, возвращаем его пользователю. Для обычных файлов мы создаём читаемый поток через fs.createReadStream и передаём его в ответ, вместе с типом содержимого, который модуль “mime” выдал для этого файла.

Код обработки DELETE будет проще:

Возможно, вам интересно, почему попытка удаления несуществующего файла возвращает статус 204 вместо ошибки. Можно сказать, что при попытке удалить несуществующий файл, так как файла там уже нет, то запрос уже исполнен. Стандарт HTTP поощряет людей делать идемпотентные запросы – то есть такие, при которых многократный повтор одного и того же действия не приводит к разным результатам.

Когда ответ HTTP не содержит данных, можно использовать код статуса 204 (“no content”). Так как нам нужно обеспечить функции обратного вызова, которые либо сообщают об ошибке, или возвращают ответ 204 в разных ситуациях, я написал специальную функцию respondErrorOrNothing, которая создаёт такой обратный вызов.

Вот обработчик запросов PUT:

Здесь нам не нужно проверять существование файла – если он есть, мы его просто перезапишем. Опять мы используем pipe для передачи данных из читаемого потока в записываемый, в нашем случае – из запроса в файл. Если создать поток не удаётся, создаётся событие “error”, о чём мы сообщаем в ответе. Когда данные переданы успешно, pipe закроет оба потока, что приведёт к запуску события “finish”. А после этого мы можем отчитаться об успехе с кодом 204.

Полный скрипт сервера доступен на сайте: eloquentjavascript.net/code/file_server.js. Его можно скачать и запустить через Node для запуска собственного файлового сервера. Конечно, его можно менять и дополнять для решения упражнений или экспериментов.

Утилита командной строки curl, общедоступная на unix-системах, может использоваться для создания HTTP запросов. Следующий фрагмент тестирует наш сервер. Опция –X используется для задания метода запроса, а –d для включения тела запроса.

Первый запрос к file.txt завершается с ошибкой, поскольку файла ещё нет. Запрос PUT создаёт файл, и глядите-ка – следующий запрос его успешно получает. После его удаления через DELETE файл снова отсутствует.

Обработка ошибок

В коде файлового сервера есть шесть мест, где мы перенаправляем исключения, когда мы не знаем, как обрабатывать ошибки. Поскольку исключения не передаются автоматически в функции обратного вызова, но передаются им как аргументы, их надо каждый раз обрабатывать персонально. Это сводит на нет преимущество обработки исключений, а именно, возможность централизованно обрабатывать ошибки.

Что будет, когда что-то реально выбросит исключение в системе? Мы не используем блоки try, потому оно будет передано на самый верх стека вызовов. В Node это приводит к прекращению выполнения программы и выводу информации об исключении (вместе с отслеживанием стека) на стандартный вывод.

Поэтому наш сервер будет падать при возникновении проблем в коде – в отличие от проблем с асинхронностью, которые будут переданы как аргументы в функции вызова. Если нам надо обрабатывать все исключения, возникающие при обработке запроса, чтобы мы точно отправили ответ, нам надо добавлять блоки try/catch в каждом обратном вызове.

Это плохо. Много программ для Node написаны так, чтобы использовать как можно меньше работы с исключениями, подразумевая что в случае возникновения исключения программа не может его обработать, и поэтому надо падать.

Ещё один подход – использование обещаний, которые были описаны в главе 17. Они ловят исключения, выброшенные функциями обратного вызова и передают их как ошибки. В Node можно загрузить библиотеку promise и использовать её для обработки асинхронных вызовов. Немногие библиотеки Node интегрируют обещания, но обычно их довольно просто обернуть. Отличный модуль “promise” с NPM содержит функцию denodeify, которая берёт асинхронную функцию вроде fs.readFile и преобразовывает её в функцию, возвращающую обещание.

Для сравнения, я написал ещё одну версию файлового сервера с использованием обещаний, которую можно найти на eloquentjavascript.net/code/file_server_promises.js. Она почище, потому что функции теперь могут возвращать результаты, а не назначать обратные вызовы, и исключения передаются неявно.

Приведу несколько строк оттуда, чтобы продемонстрировать разницу в стилях.

Объект fsp, использующийся в коде, содержит варианты функций fs с обещаниями, обёрнутыми при помощи Promise.denodeify. Возвращаемый из обработчика метода объект, со свойствами code и body, становится окончательным результатом цепочки обещаний, и он используется для определения того, какой ответ отправить клиенту.

Функция inspectPath – простая обёртка вокруг fs.stat, обрабатывающая случай, когда файл не найден. В этом случае мы заменяем ошибку на успех, возвращающий null. Все остальные ошибки можно передавать. Когда обещание, возвращаемое из этих обработчиков, обламывается, сервер отвечает кодом 500.

Node – отличная простая система, позволяющая запускать JavaScript вне браузера. Изначально она разрабатывалась для работы по сети, чтобы играть роль узла в сети. Но она позволяет делать много всего, и если вы наслаждаетесь программированием на JavaScript, автоматизация ежедневных задач с Node работает отлично.

NPM предоставляет библиотеки для всего, что вам может прийти в голову (и даже для кое-чего, что вам не придёт в голову), и она позволяет скачивать и устанавливать их простой командой. Node также поставляется с набором встроенных модулей, включая “fs” для работы с файловой системой, и “http” для запуска HTTP серверов и создания HTTP запросов.

Весь ввод и вывод в Node делается асинхронно, если только вы не используете явно синхронный вариант функции, например fs.readFileSync. Вы предоставляете функции обратного вызова, а Node их вызывает в нужное время, когда операции I/O заканчивают работу.

Упражнения

И снова согласование содержания

В главе 17 первое упражнение было посвящено созданию запросов к eloquentjavascript.net/author, спрашивавших разные типы содержимого путём передачи разных заголовков Accept.

Сделайте это снова, используя функцию Node http.request. Запросите, по крайней мере, типы text/plain, text/html и application/json. Помните, что заголовки запроса можно передавать как объект в свойстве headers, первым аргументом http.request.

Выведите содержимое каждого ответа.

Устранение утечек

Для упрощения доступа к файлам я оставил работать сервер у себя на комьпютере, в директории /home/marijn/public. Однажды я обнаружил, что кто-то получил доступ ко всем моим паролям, которые я хранил в браузере. Что случилось?

Если вам это непонятно, вспомните функцию urlToPath, которая определялась так:

Теперь вспомните, что пути, передаваемые в функцию “fs”, могут быть относительными. Они могут содержать путь “../” в верхний каталог. Что будет, если клиент отправит запросы на URL вроде следующих:

Поменяйте функцию urlToPath для устранения подобной проблемы. Примите во внимание, что на Windows Node разрешает как прямые так и обратные слеши для задания путей.

Кроме этого, помедитируйте над тем фактом, что как только вы выставляете сырую систему в интернет, ошибки в системе могут быть использованы против вас и вашего компьютера.

Создание директорий

Хотя метод DELETE работает и при удалении директорий (через fs.rmdir), пока сервер не предоставляет возможности создания директорий.

Добавьте поддержку метода MKCOL, который должен создавать директорию через fs.mkdir. MKCOL не является основным методом HTTP, но он существует, именно для этого, в стандарте WebDAV, который содержит расширения HTTP, чтобы использовать его для записи ресурсов, а не только для их чтения.

Общественное место в сети

Так как файловый сервер выдаёт любые файлы и даже возвращает правильный заголовок Content-Type, его можно использовать для обслуживания веб-сайта. Так как он разрешает всем удалять и заменять файлы, это был бы интересный сайт – который можно изменять, портить и удалять всем, кто может создать правильный HTTP-запрос. Но это всё равно был бы веб-сайт.

Напишите простую HTML страницу с простым файлом JavaScript. Разместите их в директории, обслуживаемой сервером и откройте в браузере.

Затем, в качестве продвинутого упражнения, скомбинируйте все полученные знания из книги, чтобы построить более дружественный интерфейс для модификации веб-сайта изнутри самого сайта.

Используйте форму HTML (глава 18) для редактирования файлов, составляющих сайт, позволяя пользователю обновлять их на сервере через HTTP-запросы, как описано в главе 17.

Начните с одного файла, редактирование которого разрешено. Затем сделайте так, чтобы можно было выбирать файл для редактирования. Используйте тот факт, что наш файловый сервер возвращает списки файлов по запросу директории.

Не меняйте файлы непосредственно в коде файлового сервера – если вы сделаете ошибку, вы скорее всего испортите те файлы. Работайте в директории, недоступной снаружи, и копируйте их туда после тестирования.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *