Node.js для начинающих

Node.js для начинающих

В этой статье я расскажу об основных принципах Node.js, его плюсах и минусах и покажу как начать разработку. Но перед тем как начать работать с Node.js, желательно понять разницу между Node.js и традиционными серверными языками (PHP, Python, Ruby).

Для тех кто подумывает о том, чтобы взять кредит, рекомендуем сайт acredo.ru. Понравился калькулятор кредитов — красивый и информативный.

Асинхронное программирование

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

Ты сделаешь все!

Node.js — всего лишь среда, поэтому всю работу придется делать вручную. В Node.js по умолчанию нет даже HTTP сервера! И это печалит, однако Node.js подкупает высокой производительностью веб-приложений. Всего лишь один скрипт обрабатывает все соединения с клиентом. Такое решение значительно снижает количество используемых ресурсов в приложении. Для примера, вот код простого Node.js приложения.

var i, a, b, c, max;

max = 1000000000;

var d = Date.now();

for (i = 0; i < max; i++) {
a = 1234 + 5678 + i;
b = 1234 * 5678 + i;
c = 1234 / 2 + i;
}

console.log(Date.now() - d);

А вот его эквивалент на PHP:

$a = null;
$b = null;
$c = null;
$i = null;
$max = 1000000000;
$start = microtime(true);
for ($i = 0; $i < $max; $i++) {
$a = 1234 + 5678 + $i;
$b = 1234 * 5678 + $i;
$c = 1234 / 2 + $i;
}
var_dump(microtime(true) - $start);

В следующей таблице сравнивается время выполнения обоих примеров.

Количество итераций Время в Node.js, мс. Время PHP, мс.
100 2.00 0.14
10 000 3.00 10.53
1 000 000 15.00 1119.24
10 000 000 143.00 10621.46
1 000 000 000 11118.00 1036272.19

Оба примера выполнялись в командной строке, поэтому задержки на запуск веб-сервера здесь нет. Я запускал каждый тест по 10 раз и взял средний результат. PHP оказался быстрее на малом количестве итераций, но это преимущество быстро исчезает, когда количество итераций увеличивается. Когда я завершил все тесты, то PHP оказался на 93% медленнее Node.js.

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

Модули

Node.js построен на модульной архитектуре: это сделано для упрощения создания сложных приложений. Модули похожи на библиотеки в C или units в Pascal. Каждый модуль содержит набор функций, которые относятся к «теме» этого модуля. Например, модуль http содержит функции специфичные для HTTP. Node.js также содержит несколько модулей из коробки: для работы с файловой системой, создания HTTP и TCP/UPD серверов и др.

Модуль подключается с помощью функции require():

var http = require('http');

Эта функция возвращает указанный модуль. В примере выше ссылка на модуль http хранится в переменной http.

Функция принимает на вход имя модуля. После этого Node.js проверяет папку node_modules в каталоге приложения и ищет в ней папку с названием http. Если Node.js не нашел каталог node_modules или модуль http внутри этого каталога, тогда он обратиться к глобальному кэшированному модулю. Вместо имени в функцию require() можно передавать относительный или абсолютный путь к модулю:

var myModule = require('./myModule.js');

Модули инкапсулируют части кода. Код внутри модуля в основном приватный. Это означает, что функции и переменные объявленные в модуле, доступны только внутри модуля. Но Node.js позволяет создавать общедоступные функции или/и переменные. За это отвечает объект exports. Пример:

var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};

В этом примере создается переменная PI, которую можно использовать только внутри модуля. Следующие 2 функции создают объект exports. Эти функции доступны вне модуля, потому что определены через объект exports. В результате переменная PI полностью защищена от внешнего вмешательства. Таким образом функции area и cercumference будут вести себя так как и должны(в зависимости от значения параметра r).

Глобальная область видимости

Node.js — JavaScript среда, разработанная на движке JavaScript V8 от Google. Поэтому необходимо использовать лучшие практики программирования на клиентской стороне. Например, нужно избегать объявлений в глобальной области видимости. Однако это не всегда возможно. В Node.js легко создать глобальную переменную или функцию, опуская ключевое слово var, например:

globalVariable = 1;
globalFunction = function () { ... };

Повторю еще раз, глобальных переменных и функций следует избегать, когда это возможно. Так что будьте бдительны — используйте var для объявления переменных!

Установка

Конечно, прежде чем писать и запускать приложения на Node.js, необходимо его установить. На сайте nodejs.org можно скачать инсталлятор для Windows или OS X. Для Linux можно использовать любой пакетный менеджер. Для установки Node.js нужно открыть командную строку и ввести:

sudo apt-get update
sudo apt-get install node

или

sudo aptitude update
sudo aptitude install node

Node.js есть в sid репозиториях; можете добавить их в список исходных кодов:

sudo echo deb http://ftp.us.debian.org/debian/ sid main > /etc/apt/sources.list.d/sid.list

Установка sid пакетов на старые системы может повредить вашу систему. Поэтому после установки желательно удалить /etc/apt/sources.list.d/sid.list

Установка новых модулей

В Node.js есть менеджер пакетов, который называется Node Package Manager (NPM). NPM устанавливается автоматически с Node.js, и его можно использовать для установки новых модулей. Чтобы установить новый модуль, нужно открыть командную строку, перейти в нужную папку и выполнить следующую команду:

npm install module_name

Синтаксис этой команды не зависит от операционной системы. Команда установит модуль, который указан вместо module_name.

Hello World

Первое приложение, которое я напишу на Node.js будет «Hello World!». Для этого, я создам файл, который назову hello.js и добавлю следующий код:

console.log('Hello World!');

Чтобы выполнить скрипт нужно открыть командную строку и перейти в папку с файлом hello.js и выполнить следующую команду:

node hello.js

В консоль выведется надпись «Hello World!».

HTTP сервер

Теперь я сделаю приложение посложнее, но не такое сложное как вы могли бы подумать). В коде приведены комментарии.

// подключаем http модуль.
var http = require("http");

// Создаем сервер. Функция передается как параметр при каждом запросе.
// переменная request содержит все параметры запроса.
// переменная response позволяет указать, что нужно делать при отправке ответа клиенту
http.createServer(function (request, response) {
// Добавляем обработчик события.
// Это событие происходит, когда клиент отправил данные и ждет ответ
request.on("end", function () {
// Пишем заголовки в ответ.
// 200 это код состояния HTTP (200 означает "хорошо")
// Второй параметр - это объект, который содержит поля заголовка
// Я посылаю обычный текст, с помощью Content-Type со значением text/plain
response.writeHead(200, {
'Content-Type': 'text/plain'
});
// Отправляем данные
response.end('Hello HTTP!');
});
// Слушаем 8080 порт.
}).listen(8080);

Это очень простой пример. На самом деле, клиенту можно отправить гораздо большее количество данных с помощью метода response.write(), но вызывать его нужно перед методом response.end(). Я сохранил этот код в файл http.js и ввел в консоль:

 

node http.js

Затем открыл браузер и перешел на http://localhost:8080. На странице отобразилось «Hello HTTP!».

Обработка url параметров

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

// Подключаем http модуль,
var http = require("http"),
// и url модуль, который поможет при разборе параметров запроса
url = require("url");

// Создаем сервер.
http.createServer(function (request, response) {
// Добавляем обработчик события.
request.on('end', function () {
// Разбираем запрос на аргументы и сохраняем их в переменную _get.
// Эта функция анализирует url и возвращает объект.
var _get = url.parse(request.url, true).query;
// Пишем заголовки в ответ.
response.writeHead(200, {
'Content-Type': 'text/plain'
});
// Отправляем данные и завершаем ответ.
response.end('Here is your data: ' + _get['data']);
});
// Listen on the 8080 port.
}).listen(8080);

Этот код использует метод parse() модуля url, который является основным модулем в Node.js для преобразования url в объект. У возвращаемого объекта есть свойство query, которое извлекает url параметры. Я сохранил этот код в файл get.js и выполнил следующую команду:

node get.js

Затем в браузере открыл страницу http://localhost:8080/?data=put_some_text_here.

Чтение и запись файлов

Для работы с файлами в Node.js существует модуль fs. У этого модуля есть методы fs.readFile() и fs.writeFile() для чтения и записи файлов. Я расскажу о них подробнее после знакомства с примером:

// Подключаем http модуль,
var http = require("http"),
// и модуль fs
fs = require("fs");

// Создаем http сервер.
http.createServer(function (request, response) {
// Добавляем обработчик события.
request.on("end", function () {
// Читаем файл
fs.readFile("test.txt", 'utf-8', function (error, data) {
// Пишем заголовки.
response.writeHead(200, {
'Content-Type': 'text/plain'
});
// Увеличиваем число полученное из файла.
data = parseInt(data) + 1;
// Пишем новое число в файл.
fs.writeFile('test.txt', data);
// Пишем симпатичное сообщение в ответ.
response.end('This page was refreshed ' + data + ' times!');
);
});
// Слушаем 8080 порт
}).listen(8080);

Я сохранил этот код в файл files.js. Перез запуском этого скрипта, нужно создать файл с именем test.txt в директории с files.js.

Этот код демонстирует работу методов fs.readFile() и fs.writeFile(). Каждый раз, когда сервер получает запрос, скрипт считывает число из файла, увеличивает его и записывает новое число в этот же файл.Метод fs.readFile() принимает 3 аргумента: имя файла для чтения, ожидаемую кодировку и вызываемую функцию.

Запись в файл гораздо проще. Не нужно ожидать каких-то результатов, хотя в реальном приложении нужно проверять на наличие ошибок. Метод fs.writeFile() принимает в качестве аргументов имя файла и данные для записи. Этот метод также может принимать 3-й и 4-й необязательные аргументы, для указания кодировки и функции обратного вызова.

Я запустил скрипт командой:

node files.js

Затем открыл в браузере http://localhost:8080 и перезапустил несколько раз. Может показаться, что в коде была ошибка, т.к. число увеличилось на 2. Это не ошибка, потому что в действительности было послано 2 запроса. Первый запрос автоматически сделал браузер, когда запросил favicon.ico и вторым запросом был http://localhost:8080.

Хотя технически это не ошибка, такое поведение скрипта не очевидно. Поэтому я добавил исправление, которое проверяет url. Вот исправленный код:

// Подключаем http модуль,
var http = require("http"),
// и модуль fs
fs = require("fs");

// Создаем http сервер.
http.createServer(function (request, response) {
// Добавляем обработчик события.
request.on('end', function () {
// Проверяем запрос /
if (request.url == '/') {
// Читаем файл.
fs.readFile('test.txt', 'utf-8', function (error, data) {
// Пишем заголовки.
response.writeHead(200, {
'Content-Type': 'text/plain'
});
// Увеличивем число полученное из файла.
data = parseInt(data) + 1;
// Пишем увеличенное число в файл.
fs.writeFile('test.txt', data);
// Пишем симпатичное сообщение в ответ.
response.end('This page was refreshed ' + data + ' times!');
});
} else {
// Файл не найден
response.writeHead(404);
// и завершаем запрос без отправки каких-либо данных.
response.end();
}
});
// Слушаем 8080 порт.
}).listen(8080);

Теперь скрипт работает так, как ожидается.

Доступ к Mysql

Традиционные серверные технологии имеют встроенные средства подключения и отправки запросов к базе данных. Для Node.js нужно установить специальную библиотеку. Я выбрал наиболее стабильную и простую в использовании node-mysql. Полностью модуль назыается mysql@2.0.0-alpha2(после @ идет версия). Чтобы установить данный модуль, я открыл консоль, перешел в директорию, где хранятся скрипты и выполнил следующую команду:

npm install mysql@2.0.0-alpha2

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

// Подключаем http модуль,
var http = require('http'),
// и mysql модуль.
mysql = require("mysql");

// Создаем соединение.
// Настройки по умолчанию должны быть изменены в соответсвии с настройками mysql.
var connection = mysql.createConnection({
user: "root",
password: "",
database: "db_name"
});

// Создаем http сервер.
http.createServer(function (request, response) {
// Добавляем обработчик события.
request.on('end', function () {
// Запрос к базе данных.
connection.query('SELECT * FROM your_table;', function (error, rows, fields) {
response.writeHead(200, {
'Content-Type': 'x-application/json'
});
// Отправляем данные в json формате.
// Строки переменной содержат результат запроса.
response.end(JSON.stringify(rows));
});
});
// Слушаем 8080 порт.
}).listen(8080);

Запрос к базе данных делается просто, нужно в методе query написать сам запрос и функцию обратного вызова. В реальном приложении, сначала нужно проверить были ли ошибки (параметр error будет undefined если были ошибки) и ответ зависит от того, выполнился ли запрос или нет. Также обратите внимание, что я установил Content-Type в x-application/json, оно указывает что MIME тип действительно является json. Параметр rows содержит результат запроса, который я легко конвертировал в JSON структуру ипользуя метод JSON.stringify().

Я сохранил этот код в файл mysql.js и выполнил команду:

node mysql.js

Затем перешел в браузере на http://localhost:8080 и браузер предложил загрузить файл в JSON формате.

Заключение

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

Node.js — это перспективная технология и отличный выбор для высоконагруженных приложений. Это было доказано такими корпорациями, как Microsoft, eBay и Yahoo. Если вы не уверены в выборе хостинга для вашего вебсайта или приложения, вы всегда можете использовать дешевое VPS решение или различные облачные сервисы, например Microsoft, Azure и Amazon EC2.

Перевод статьи Node.js for beginners.

Расскажите друзьям

Оцените статью:
  • 1
  • 2
  • 3
  • 4
  • 5

Комментарии — 31

Stepan
Долго не решался прочитать про этот node.js, из-за не надобности.
Теперь имею некоторое представление.
Написано просто и ясно.
#
Stepan
Кир
> Node.js — JavaScript среда, разработанная в Google на движке JavaScript V8. Поэтому необходимо
> использовать лучшие практики программирования на клиентской стороне.
node.js разработан не в гугле, следовательно что? :)
#
Кир
Andrey Zaytsev
Вообще говоря, статья откровенно слабая, главное надо помнить, что nodejs это не просто новое модное напрвление, а довольно сложная штука, и использовать его для построения сайтов среднего уровня и ниже - это просто глупо. Без достаточного уровня и опыта в JS будут сплошные проблемы и баги в коде, для большинства случаев подойдут уже испытанные технологии (PHP, например), для которых есть много готовых наработок. Те же большие корпорации, перечисленные в статье, не используют nodejs для организации сайтов, они его используют для решения задач, которые подразумевают высокую нагрузку и большое число одновременных запросов данных к серверу.
#
Andrey Zaytsev
Евгений Земченков
Это же перевод :)

И да перечисленные корпорации не используют Node.js для организации сайтов, но в статье про это и не написано)
Евгений Земченков
Можно воспользоваться вот этим учебником http://nodebeginner.ru/
#
Евгений Земченков  
Alex
Полезный ресурс
#
Alex
Виталий
движок JavaScript V8 разработан в Google. А v8?
Gabda
Спасибо автору. Познавательно и интересно.
#
Gabda
Елена
Мне кажется php все равно как-то практичней.
Самый
Хотя бы php хорошо выучить а потом можно и за Node.js браться
wot
я полностью согласен с людьми по поводу Php
#
wot
wot
я полностью согласен с людьми по поводу ПХП
#
wot
alexandr
Прикольно получается - завершаем запрос (response.end() ) в теле функции (request.on('end', function (){...}) ), которая сработает ТОЛЬКО при завершении запроса. Это бесконечный цикл, господа.
#
alexandr
alexandr
А так для быстрого старта отличная статья
#
alexandr
Фёдор
Вот бы практических примеров побольше и по сложнее, по практическим пример проще понять. От теории уже тошнит.(пытаюсь понять сие чудо без должных знаний в js)
chat
Wery nice thanks like it page.
#
chat
t?rk? dinle
Полезный ресурс
kester
chat, хотел показаться умным? Не вышло.(английский подучи)
Спасибо за перевод и комментарии, стал немного понимать что оно такое и с чем его едят.
Использовать его не собираюсь, по крайней мере пока.
#
kester
Airoo
Очень полезная статья! Думаете это перспективная технология для создания приложений в будущем?
Serg
Теперь хоть понятно, что за штука такая. Но думаю, что применима только в больших корпорациях. Плюсы производительности только при огромном количестве запросов. А кто может похвастаться миллионной посещаемостью в сутки ? Гугл да яхо. При посещаемости 2-3к в сутки преимуществ никаких. За статью спасибо, просто и понятно.
#
Serg
Теннис
Спасибо за пост
Андрей
А когда-то и электричество было в диковинку :) Электрофикация петербургского железнодорожного узла: http://chevo.su/?p=156 журнал "Огонёк", 1912-й год.
witosp
Спасибо, полезная статья - но ваших примеров использования кажется не хватает
sunsey
Полезная статья, весьма благодарен
#
sunsey
emma
Менеджмент как наука инновационные стратегии менеджмент.
Экономика финансы инвестиционные решения предприятия.
Креативный менеджмент стратегии развития персонала управление риском.
Мотивация персонала эффективность труда управление персоналом.
Финансы управление персоналом экономическая эффективность.
#
emma
Владимир-Седьмой
Ребята, смотрите, разница с PHP огромна при нагрузке. Это можно использовать в вебирах в онлайн-играх. В близжайшем будущем появится интернет-ораторское искусство, необходимый сервис предоставит node
#
Владимир-Седьмой
Владимир-Седьмой
Спасибо автору и переводчику статьи
#
Владимир-Седьмой
Андрей
Нормик! Разобрался чутка и с этим вопросиком...
Михаил
видео загрузчик на node.js http://siteacademy.ru/index.php/jquery/74-how-to-create-a-resumable-video-uploade-in-node-js
#
Михаил

Новый комментарий

как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть
как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть

metin2 pvp metin2 pvp serverler pvp serverler