Статьи

Изучение JavaScript на стороне сервера с Node.js

На данный момент Node.js — это настоящий гудок, который упрощает создание высокопроизводительных веб-приложений в реальном времени. Это позволяет использовать JavaScript сквозным образом как на сервере, так и на клиенте. Из этого туториала вы узнаете, как установить Node и вашу первую программу «Hello World», чтобы создать масштабируемый потоковый сервер Twitter.


NodeJS

JavaScript традиционно запускается только в веб-браузере, но в последнее время появился значительный интерес к его переносу и на серверную сторону благодаря проекту CommonJS . Другие серверные среды JavaScript включают в себя Jaxer и Narwhal . Однако Node.js немного отличается от этих решений, потому что он основан на событиях, а не на потоках. Веб-серверы, такие как Apache, которые используются для обслуживания PHP и других CGI-скриптов, основаны на потоках, поскольку они порождают системный поток для каждого входящего запроса. Хотя это хорошо для многих приложений, модель, основанная на потоках, плохо масштабируется со многими долгоживущими соединениями, которые необходимы для обслуживания приложений реального времени, таких как Friendfeed или Google Wave .

«Каждая операция ввода-вывода в Node.js является асинхронной …»

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


Node.js работает на Unix-системах, таких как Mac OS X, Linux и FreeBSD. К сожалению, Windows пока не поддерживается, поэтому, если вы являетесь пользователем Windows, вы можете установить его на Ubuntu Linux с помощью Virtualbox. Для этого следуйте этому руководству . Вам нужно будет использовать терминал для установки и запуска Node.js.

  1. Загрузите последнюю версию Node.js с nodejs.org (последняя версия на момент написания этой статьи — 0.1.31) и разархивируйте ее.
  2. Откройте терминал и выполните следующие команды.
    1
    2
    3
    cd /path/to/nodejs
    make
    sudo make install

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


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

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

Выполнение этих двух строк так же просто, как выполнение команды node с именем файла javascript в качестве аргумента.

1
node test.js

Это выведет «Hello World!» в командной строке при запуске.

Чтобы создать HTTP-сервер, вам необходим модуль http .

Этот скрипт импортирует модули sys и http и создает HTTP-сервер. Анонимная функция, которая передается в http.createServer будет вызываться всякий раз, когда на сервер поступает запрос. Как только сервер создан, ему предписывается прослушивать порт 8080. Когда поступает запрос к серверу, мы сначала отправляем заголовки HTTP с типом содержимого и кодом состояния 200 (успешно). Затем мы отправляем «Hello World!» и закройте соединение. Вы можете заметить, что мы должны явно закрыть соединение. Это позволит очень легко передавать данные клиенту, не закрывая соединение. Если вы запустите этот скрипт и перейдете по http://localhost:8080/ в своем браузере, вы увидите «Hello World!»


Итак, мы создали HTTP-сервер, но он не отправляет ничего, кроме «Hello World», независимо от того, по какому URL вы переходите. Любой HTTP-сервер должен иметь возможность отправлять статические файлы, такие как файлы HTML, изображения и другие файлы. Следующий код делает именно это:

Мы начнем с требования всех модулей, которые нам понадобятся в нашем коде. Это включает в себя модули sys , http , url , path и fs или файловую систему. Далее мы создаем HTTP-сервер, как мы делали раньше. На этот раз мы будем использовать модуль url чтобы проанализировать входящий URL-адрес запроса и найти путь к файлу, к которому осуществляется доступ. Мы находим фактическое имя файла на жестком диске сервера, используя path.join , который соединяет process.cwd() или текущий рабочий каталог с путем к запрашиваемому файлу. Затем мы проверяем, существует ли файл, что является асинхронной операцией и, следовательно, требует обратного вызова. Если файл не существует, пользователю отправляется сообщение 404 Not Found, и функция возвращается. В противном случае мы читаем файл, используя модуль fs используя «двоичную» кодировку, и отправляем файл пользователю. Если при чтении файла произошла ошибка, мы предоставляем пользователю сообщение об ошибке и закрываем соединение. Поскольку все это асинхронно, сервер может обслуживать другие запросы при чтении файла с диска независимо от его размера.

Если вы запустите этот пример и перейдете по http://localhost:8080/path/to/file , этот файл будет показан в вашем браузере.


Основываясь на нашем статическом файловом сервере, мы создадим сервер в Node.js, который транслирует твиты клиенту, который обслуживается через наш статический файловый сервер. Для начала нам понадобится один дополнительный модуль в этом примере: модуль events . В Node есть концепция EventEmitter , которая используется повсеместно для обработки прослушивателей событий для асинхронных задач. Так же, как в jQuery или другой клиентской JavaScript-инфраструктуре, где вы привязываете слушателей событий к таким вещам, как щелчки мыши и запросы AJAX, Node позволяет привязывать слушателей событий ко многим вещам, некоторые из которых мы уже использовали. К ним относятся все операции ввода-вывода, такие как чтение файла, запись файла, проверка наличия файла, ожидание HTTP-запросов и т. Д. EventEmitter абстрагирует логику привязки, отмены привязки и запуска таких прослушивателей событий. Мы будем использовать EventEmitter для уведомления слушателей о загрузке новых твитов. Первые несколько строк нашего твит-стримера импортируют все необходимые модули и определяют функцию для обработки статических файлов, которая была взята из нашего предыдущего примера.

Ранее мы использовали модуль http для создания сервера, но также можно создать HTTP-клиента с использованием этого модуля. Мы будем создавать HTTP-клиент для загрузки твитов с общедоступной временной шкалы Twitter, который выполняется функцией get_tweets .

Сначала мы создаем HTTP-клиент на порту 80 для api.twitter.com и создаем новый EventEmitter . Функция get_tweets создает HTTP-запрос «GET» к общедоступной временной шкале Twitter и добавляет прослушиватель событий, который будет срабатывать при ответе серверов Twitter. Поскольку Node.js является асинхронным, данные в теле ответа поступают в виде фрагментов, которые воспринимаются прослушивателем «данных» ответа. Этот слушатель просто добавляет чанк к переменной body . Как только все чанки введены, запускается «конечный» слушатель, и мы анализируем входящие данные JSON. Если возвращается более одного твита, мы tweet_emitter событие «твиты» на наш tweet_emitter и передаем массив новых твитов. Это приведет к тому, что все прослушиватели событий прослушивают событие «твиты» и отправят новые твиты каждому клиенту. Мы получаем новые твиты каждые пять секунд, используя setInterval .

Наконец, нам нужно создать HTTP-сервер для обработки запросов.

Как и в случае с нашим статическим файловым сервером, мы создаем HTTP-сервер, который прослушивает порт 8080. Мы анализируем запрошенный URL-адрес, и если URL-адрес равен "/stream" , мы его обработаем, в противном случае мы передаем запрос на отключение. на наш статический файловый сервер. Потоковая передача состоит из создания слушателя для прослушивания новых твитов на нашем tweet_emitter , который будет запускаться нашей функцией get_tweets . Мы также создаем таймер для уничтожения запросов, которые длятся более 10 секунд, отправляя им пустой массив. Когда поступают новые твиты, мы отправляем твиты в виде данных JSON и очищаем таймер. Вы увидите, как это работает лучше, увидев код на стороне клиента, который приведен ниже. Сохраните его как test.html в том же каталоге, что и серверный JavaScript.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
    <head>
        <title>Tweet Streamer</title>
        <script type=»text/javascript» src=»http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js»></script>
    </head>
    <body>
        <ul id=»tweets»></ul>
        <script type=»text/javascript»>
        var tweet_list = $(«#tweets»);
         
        function load_tweets() {
            $.getJSON(«/stream», function(tweets) {
                $.each(tweets, function() {
                    $(«<li>»).html(this.text).prependTo(tweet_list);
                });
                load_tweets();
            });
        }
         
        setTimeout(load_tweets, 1000);
        </script>
    </body>
</html>

Здесь у нас есть простая HTML-страница, которая импортирует библиотеку jQuery и определяет неупорядоченный список для размещения твитов. Наш клиентский JavaScript кэширует список твитов и запускает функцию load_tweets через одну секунду. Это дает браузеру достаточно времени, чтобы завершить загрузку страницы, прежде чем мы начнем AJAX-запрос к серверу. Функция load_tweets очень проста: она использует функцию getJSON jQuery для загрузки /stream . Когда приходит ответ, мы перебираем все твиты и добавляем их в список твитов. Затем мы снова вызываем load_tweets . Это эффективно создает цикл, который загружает новые твиты, который истекает через десять секунд из-за тайм-аута на сервере. Всякий раз, когда появляются новые твиты, они отправляются клиенту, который поддерживает постоянное соединение с сервером. Эта техника называется длительным опросом.

Если вы запустите сервер с помощью node и перейдете по http://localhost:8080/test.html , вы увидите поток общедоступных временных шкал Twitter в своем браузере.


Node.js — это очень интересная технология, которая позволяет легко создавать высокопроизводительные приложения в реальном времени. Я надеюсь, что вы сможете увидеть его преимущества и использовать его в некоторых своих приложениях. Благодаря отличной модульной системе Node, в вашем приложении легко использовать предварительно написанный код, и существует множество сторонних модулей, доступных практически для всего, включая слои подключения к базе данных, механизмы шаблонов, почтовые клиенты и даже целые платформы, соединяющие все эти вещи вместе. Вы можете увидеть полный список модулей в вики Node.js , а также другие руководства по Node можно найти в How To Node . Я также рекомендую вам посмотреть видео от JSConf, в котором Райан Даль, создатель Node, описывает философию дизайна Node. Это доступно.

Я надеюсь, вам понравился этот урок. Если у вас есть какие-либо комментарии, вы можете оставить их здесь или отправить мне сообщение в Twitter . Удачного кодирования!