Глобальные объекты: Объекты global и process

Глобальные объекты: Объекты global и process
3 (60%) 2 votes

Два важнейших объекта в Node — global и process . Объект global немного похож на глобальный объект в браузере, хотя между ними существуют очень серьезные различия. Объект process , напротив, существует только в Node.

Объект global

В браузере переменная, объявленная на верхнем уровне, объявляется глобально. В Node дело обстоит иначе. Переменная, объявленная в модуле или приложении Node, не обладает глобальной доступностью; она ограничивается модулем или приложением. Таким образом, можно объявить «глобальную» переменную с именем str в модуле и в приложении, использующем этот модуль, и никакого конфликта не будет.

Для демонстрации создадим простую функцию, которая прибавляет число к базовому значению и возвращает результат (название файла — add2.js). Функция будет создана как библиотека JavaScript для использования в веб странице, а также как модуль для использования в приложении Node. Код объявляет переменную base, присваивает ей значение 2, после чего прибавляет переданное число:

var base = 2;
function addtwo(input) {
  return parseInt(input) + base;
}

Затем создадим очень простой модуль (название файла — addtwo.js), который делает то же самое, но с использованием синтаксиса модуля Node.

var base = 2;
exports.addtwo = function(input) {
  return parseInt(input) + base;
};

А теперь посмотрим, чем различается концепция глобальности в двух разных средах. Файл add2.js используется в веб-странице, которая также объявляет переменную base:

<!DOCTYPE html>
<html>
 <head>
  <script src="add2.js"></script>
  <script>
   var base = 10;
   console.log(addtwo(10));
  </script>
 </head>
 <body>
 </body>
</html>

При обращении к веб-странице в браузере на консоли браузера выводится значение 20 (вместо ожидаемого 12). Дело в том, что все переменные, объявленные за пределами функции в JavaScript, добавляются в один глобальный объект. Объявляя новую переменную с именем base в веб странице, мы переопределяем значение во включенном файле сценария.

Теперь используем модуль addtwo в приложении Node:

var addtwo = require('./addtwo').addtwo;
var base = 10;
console.log(addtwo(base));

В приложении Node результат равен 12. Объявление новой переменной басе в приложении Node никак не повлияло на значение base в модуле, потому что они существуют в разных глобальных пространствах имен.

Устранение общего пространства имен — безусловное усовершенствование, но оно не универсально. Объект global во всех средах предоставляет доступ к глобально доступным объектам и функциям Node , включая объект процесс (см. далее). Чтобы убедиться в этом, просто добавьте следующую команду в файл и запустите приложение. Команда выводит все глобально доступные объекты и функции:

console.log(global);



Объект process

Объект process принадлежит к числу важнейших компонентов среды Node, так как он предоставляет информацию о среде выполнения. Кроме того, через объект process выполняется стандартный ввод/вывод, вы можете корректно завершить приложение Node и даже выдать сигнал при завершении итерации в цикле событий Node.

Сейчас мы рассмотрим получение информации о среде выполнения объекта process, а также исключительно важные средства стандартного ввода/вывода.

Объект process предоставляет доступ к информации как о среде Node, так и о среде выполнения программы. Для получения информации мы воспользуемся параметром командной строки -p , который выполняет сценарий и возвращает полученный результат. Например, для проверки свойства process. versions введите следующую команду:

$ node -p "process.versions"

{ http_parser: ‘2.5.0’,
node: ‘4.2.1’,
v8: ‘4.5.103.35’,
uv: ‘1.7.5’,
zlib: ‘1.2.8’,
ares: ‘1.10.1-DEV’,
icu: ‘56.1’,
modules: ’46’,
openssl: ‘1.0.2d’ }

Команда выводит список различных компонентов Node и зависимостей, включая версии v8, OpenSSL (библиотека, используемая для безопасной передачи данных), собственно Node и т. д.

Свойство process.env предоставляет богатую информацию о том, что Нодье знает о вашей среде разработки:

$ node -p "process.env"

Особенно интересно проанализировать различия между архитектурами (например, Linux и Windows).

Чтобы просмотреть содержимое process.release, введите следующую команду:

$ node -p "process.release"

Полученный результат зависит от того, что установлено на вашем компьютере. И в LTS, и в среде текущей версии будет выведено имя приложения, а также URL исходного кода. Но в LTS также будет выведено дополнительное свойство:

$ node -p «process.release.lts»
‘Argon’

Однако при обращении к тому же значению в текущей версии (например, v6) будет получен другой результат:

$ node -p «process.release.lts»
undefined

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

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

Стандартные потоки представляют собой заранее определенные каналы передачи данных между приложением и средой: стандартный ввод ( stdin ), стандартный вывод ( stdout ) и стандартный поток ошибок ( stderr ). В приложении Node эти каналы обеспечивают взаимодействие между приложением Нодье и терминалом, своего рода механизм прямого «общения» с приложением.

Node поддерживает каналы с тремя функциями process:

  • process.stdin : поток с поддержкой чтения для stdin;
  • process.stdout : поток с поддержкой записи для stdout;
  • process.stderr : поток с поддержкой записи для stderr.

Вы не можете закрывать эти потоки в своем приложении. Поддерживается только чтение данных из канала stdin и запись в каналы stdout и stderr.

Функции ввода/вывода process наследуют от EventEmitter, это означает, что они могут генерировать события, а вы можете перехватывать эти события и обрабатывать любые данные. Чтобы обработать входные данные с использованием process.stdin , прежде всего необходимо назначить кодировку потока. Если этого не сделать, вы получите результаты в виде буфера, а не в виде строки:

process.stdin.setEncoding('utf8');

Затем начинается прослушивание события readable , которое сообщает о поступлении блока данных, готового к чтению. Затем функция process.stdin. read() используется для чтения данных, и если данные отличны от null, они копируются в process.stdout при помощи функции process.stdout.write():

process.stdin.on('readable', function() {
  var input = process.stdin.read();
  if (input !== null) {
    // Эхо-вывод текста
    process.stdout.write(input);
  }
});

В принципе можно пропустить назначение кодировки и получить те же результаты; программа будет читать буфер и выводить буфер, но для пользователя приложения все выглядит так, словно вы работаете с текстом (строка). На самом деле это не так. Следующая функция process , которую мы рассмотрим, демонстрирует эти различия.

Мы раньше создали очень простой веб-сервер, который прослушивал запрос и выводил сообщение. Чтобы завершить программу, вам придется либо уничтожить процесс с использованием сигнала, либо нажать клавиши Ctrl+C. Также возможен другой вариант: завершить приложение из кода самого приложения при помощи process.exit() . Вы даже можете передать информацию о том, успешно ли завершилось приложение или произошла ошибка.

Мы изменим тестовое приложение ввода/вывода так, чтобы оно «прослушивало» строку выхода и при ее обнаружении программа завершалась.

process.stdin.setEncoding('utf8');

process.stdin.on('readable', function() {
  var input = process.stdin.read();
  if (input !== null) {
    // Эхо-вывод текста
    process.stdout.write(input);
    var command = input.trim();
    if (command == 'exit')
      process.exit(0);
  }
});

Если запустить это приложение, любая введенная строка будет немедленно повторяться в выводе. А если ввести команду exit , то приложение завершается, не требуя нажатия Ctrl+C.

Если убрать вызов функции process.stdin.setEncoding() в начале кода, произойдет ошибка. Дело в том, что буферы не поддерживают функцию trim(). Можно преобразовать буфер в строку, а затем выполнить trim:

var command = input.toString().trim();

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

Запись в объект process.stderr выполняется при возникновении ошибки. Почему именно этот объект, а не process.stdout ? По той же причине, по которой был создан канал stderr: чтобы отделить ожидаемый вывод от возникающих проблем. В некоторых системах вывод stderr даже может обрабатываться отдельно от stdout (например, сообщения stdout сохраняются в журнале, а вывод stderr выводится на консоль).


Об авторе

Занимаюсь программированием уже более 7 лет. Часто использую JavaScript (Node.js) и Python.

Комментарии