Изучаем nodejs pdf
Dating > Изучаем nodejs pdf
Last updated
Dating > Изучаем nodejs pdf
Last updated
Download links: → Изучаем nodejs pdf → Изучаем nodejs pdf
Конечно, имеется много вещей, которые мы не обсудили: как общаться с базой данных, как писать unit-тесты, как создавать внешние модули, с возможностью инсталяции через NPM или даже что-нибудь простое, например, как обрабатывать GET-запросы. Write для отправки текста «Hello World» в теле HTTP-ответа. Другие статьи по теме Источник: Absolute Beginners Guide to Node.
Если вам посчастливилось жить в городе, в котором намечается , я настоятельно рекомендую её посетить. Модуль Express для node. Есть ли что-то, что я могу почитать по дороге на работу? Тем не менее, вы постоянно следили за JavaScript, вы видели, что с появлениям JQuery, Prototype и других фреймворков этот язык стал больше, чем просто window. По целям использования Node сходен с фреймворками Twisted на языке Python и EventMachine на Ruby. В JavaScript нет такой штуки как sleep , поэтому мы будем использовать хитрый хак. Предложены упражнения разной сложности: от очень простых до реально сложных. С помощью этого практического руководства вы сможете быстро овладеть основами Node.
Далее, мы остановимся на написании традиционного «Hello world»-приложения, которое является наиболее простым примером «что-то делающего» кода Node. Пока вы ждёте возвращения результата от базы данных, Node может обрабатывать больше запросов. Это первый проблеск, который я называю «продвинутый» JavaScript, но давайте всё по порядку. Соответственно, изменим функцию route в нашем файле router.
Node.js для начинающих - Здесь нет стандартной или принудительной организации того, какие файлы куда идут.
Правки: spmbt 2013-03-24 О проекте Цель данного документа — помочь вам начать разработку приложений на Node. Это больше, чем обычный «Hello world»-туториал. Статус Вы читаете финальную версию этой книги, в обновлениях исправляются только ошибки или отражаются изменения в новых версиях Node. Последнее обновление 12 Февраля 2012. Код примеров этой книги тестировался на Node. Целевая аудитория Вероятно, документ будет полезен читателям с базовыми знаниями, примерно, как у меня: опыт работы хотя бы с одним объектно-ориентированным языком, таким как Ruby, Python, PHP или Java, небольшой опыт в Javascript и полный новичок в Node. Документ рассчитан на разработчиков, уже знакомых с другими языками программирования. Это значит, что здесь не приводится объяснение действительно базовых вещей, таких как типы данных, переменные, управляющие структуры и т. Вы должные разбираться в этих понятиях, чтобы понимать эту книгу. Однако, поскольку функции и объекты в JavaScript отличаются от своих аналогов в других языках, они будут описаны достаточно подробно. Структура учебника Прочитав данный документ до конца, вы сможете создать веб-приложение, которое позволит пользователям просматривать веб-страницы и загружать файлы. Это, конечно, не изменит мир, но мы будем стараться и научимся писать не просто куски кода, которых «достаточно», чтобы сделать это возможным, но и создадим простой, полноценный framework для чистого разделения различных аспектов вашего приложения. Скоро вы увидите, что я имею в виду. Мы начнём с выяснения того, чем JavaScript в Node. Далее, мы остановимся на написании традиционного «Hello world»-приложения, которое является наиболее простым примером «что-то делающего» кода Node. Тогда мы обсудим, какое «реальное» приложение мы хотим создать, проанализируем компоненты, которые необходимо реализовать для написания данного приложения, и начнём работать над каждым из них, шаг за шагом. Как и было обещано, по пути мы узнаем о некоторых продвинутых понятиях JavaScript, о том как их использовать и посмотрим, почему разумно использовать эти понятия вместо привычных нам в других языках программирования. Исходный код законченного приложения доступен в. Эта глава позволит вам понять, имеет ли смысл читать дальше. Скорее всего, как и в моем случае, вы начали свой путь в веб-разработке с написания простых статических HTML-документов. Вместе с этим, вы познакомились с веселой штукой, называемой JavaScript, но использовали его исключительно в простых случаях, добавляя интерактивности на ваши веб-странички. Что вы хотели узнать — так это действительно полезные вещи; вы хотели знать, как создать сложный сайт. Для этого вы изучали PHP, Ruby, Java и начинали писать backend-код. Тем не менее, вы постоянно следили за JavaScript, вы видели, что с появлениям JQuery, Prototype и других фреймворков этот язык стал больше, чем просто window. Однако, это всё ещё относилось к frontend-разработке. Конечно, jQuery — очень мощный инструмент, но всякий раз, когда вы приправляли ваш сайт разными jQuery-«фишками», в лучшем случае, вы были JavaScript- пользователем нежели JavaScript- разработчиком. А потом пришел Node. JavaScript на сервере: насколько это хорошо? И вы решили, что пора проверить старый новый JavaScript. И на этот раз — по-настоящему. В этом — как раз и проблема. JavaScript живёт двумя, может даже тремя разными жизнями: весёлый маленький DHMTL-помощник из середины 90-х годов, более серьезный frontend-инструмент в лице jQuery и наконец серверный server-side, backend JavaScript. По этой причине не так просто найти информацию, которая поможет вам познать правильный JavaScript, пригодный для написания Node. Это — наиболее правильный подход. Вы — уже опытный разработчик, вы не хотите изучать новые технологии поверхностно, просто валяя дурака. Вы хотите быть уверенным, что вы подходите к проблеме под правильным углом. Конечно, существует отличная документация по Node. Моя цель заключается в обеспечении вас руководством. Предупреждение Существуют действительно отличные специалисты в области JavaScript. Я не из их числа. Я — действительно, тот парень, о котором написано в предыдущем параграфе. Я знаю кое-что о разработке backend веб-приложений, но я всё ещё новичок в «реальном» JavaScript и всё ещё новичок в Node. Я узнал некоторые продвинутые аспекты JavaScript совсем недавно. Вот почему эта книга не из разряда «от новичка к эксперту», а скорее «от новичка к продвинутому новичку». Если всё удастся, то этот документ станет тем руководством, которое я хотел бы иметь, когда начинал в Node. Server-side JavaScript Первая инкарнация JavaScript жила в теле браузера. Но это всего лишь контекст. Он определяет, что вы можете делать с языком, но не говорит о том, что язык сам по себе может сделать. JavaScript это «полноценный» язык: вы можете использовать его в различных контекстах и достичь всего того, что можете достичь с другими «полноценными» языками. Чтобы ваш JavaScript код выполнился на вычислительной машине вне браузера на backend , он должен быть интерпретирован и, конечно же, выполнен. Именно это и делает Node. Для этого он использует движок V8 VM от Google — ту же самую среду исполнения для JavaScript, которую использует браузер Google Chrome. Для того чтобы их использовать, вам необходимо установить Node. Вместо повторения всего процесса установки здесь, я просто приглашу вас посетить. Пожалуйста, вернитесь обратно после успешной установки. «Hello world» Хорошо, давайте пойдём сразу с места в карьер и напишем наше первое Node. Откройте ваш любимый редактор и создайте файл под названием helloworld. Мы хотим вывести строку «Hello world» в консоль, для этого пишем следующий код: console. Ладно, всё это скучно, правда? Давайте напишем что-нибудь полезное. Полномасштабное веб-приложение с Node. Конечно, вы могли бы достичь этой цели, немного погуглив и поговнокодив. Но это не то, что нам нужно. Кроме того, мы не хотим писать только простой код для достижения цели, каким бы он элегантным и корректным ни был. Мы будем интенсивно наращивать больше абстракции, чем это необходимо, чтобы понять как создавать более сложные Node. Задачи Давайте проанализируем наше приложение. Давайте подумаем о том, как бы мы реализовали это на PHP. Это относится к первому пункту наших задач, то есть, «принимать HTTP-запросы и отправлять готовые веб-странички пользователю» — вещи, которые PHP сам не делает. Потому что в Node. Действительно, наше веб-приложение и веб-сервер — в сущности, одно и тоже. Может показаться, что это приведет к лишней работе, но сейчас вы увидите, что с Node. Давайте просто начнём реализовывать нашу первую задачу — HTTP-сервер. Реализация приложения Простой HTTP-сервер Когда я подошел к моменту создания своего первого «реального» Node. Я должен делать всё в одном файле? Большинство учебных пособий в интернете учат как создавать простой HTTP-сервер в Node. Что, если я хочу быть уверенным, что мой код останется читабельным по мере реализации всё большего функционала. На самом деле, достаточно легко отыскивать проблемные участки вашего кода, который разделён на модули. Это позволяет вам иметь чистый главный файл, который вы исполняете в Node. Так, давайте создадим главный файл, который мы будем использовать для запуска нашего приложения, и файл модуля, в котором будет находиться наш HTTP-сервер. Я думаю, это более-менее традиционно назвать главным файлом index. А код нашего сервера имеет смысл поместить в файл под названием server. Давайте начнём с модуля сервера. Вы написали работающий HTTP-сервер. Давайте проверим его, запустив и протестировав. Во-первых, выполните ваш скрипт в Node. Должна вывестись веб-страница со строкой «Hello world». Правда, это довольно интересно? Как насчёт того, чтобы поговорить о том, что здесь происходит и оставить на потом вопрос о том, как организовать наш проект? Я обещаю, мы вернемся к нему. Анализ нашего HTTP-сервера Хорошо, тогда давайте проанализируем, что здесь действительно происходит. Первая строчка подключает http-модуль, который поставляется вместе с Node. Далее, мы вызываем одну из функций http-модуля createServer. Эта функция возвращает объект, имеющий метод listen, принимающий числовое значение порта нашего HTTP-сервера, который необходимо прослушивать. Пожалуйста, проигнорируйте функцию, которая определяется внутри скобок http. Действительно интересная и, если вы привыкли к более консервативным языкам как PHP, довольно странная часть — это определение функции там, где вы бы ожидали увидеть первый параметр для createServer. Оказывается, эта определяемая функции и есть первый и только параметр, который мы передаём в createServer при вызове. Потому что в JavaScript функции могут быть переданы как параметр в другую функцию. Передача функций в качестве параметра Вы можете в качестве примера сделать что-то подобное: function say word { console. Здесь мы передаём функцию say как первый параметр функции execute. Не значение, которое возвращает функция say, а саму функцию say! Таким образом, say становится локальной переменной someFunction внутри execute и execute может вызвать функцию в этой переменной вот так: someFunction то есть, добавив скобки. Конечно же, так как say принимает один параметр word , execute может передать какое-либо значение в качестве этого параметра, когда вызывает someFunction. Мы можем, что мы и сделали, передать функцию как параметр в другую функцию. Но мы не обязаны применять этот косвенный способ, когда сначала определяется функция, а потом передаётся как параметр. Мы можем определить и передать функцию как параметр в другую функцию прямо на месте: function execute someFunction , value someFunction value ; execute function word { console. Из-за того, что нам даже не надо давать имя этой функции, её называют анонимная функция. Это первый проблеск, который я называю «продвинутый» JavaScript, но давайте всё по порядку. А сейчас давайте просто примем то, что в JavaScript мы можем передать функцию как параметр, когда вызываем другую функцию. Мы можем сделать это путём присвоения нашей функции переменной, которую му передаем, или путём определения функции для передачи на месте. Событийно-ориентированные обратные вызовы Ответ на вопрос a не так легко дать по крайней мере для меня , и b кроется в самой природе работы Node. Возможно, вы захотите занять немного своего времени и почитать отличный пост Felix Geisendörfer , чтобы прояснить этот момент. Все сводится к тому факту, что Node. Ах да, я тоже до конца не понимаю, что это значит. Но я постараюсь объяснить, почему это так важно для тех, кто хочет писать веб-приложения в Node. Когда вызываем метод http. Мы также хотим что-нибудь сделать, когда приходит HTTP-запрос на этот сервер. Проблема состоит в асинхронности: запрос происходит в любой момент времени, в то время как у нас только один процесс, в котором запущен наш сервер. Когда пишем PHP-приложения, мы не беспокоимся обо всем этом: всякий раз, когда приходит HTTP-запрос, веб-сервер обычно Apache ответвляет новый процесс специально для этого запроса и запускает соответствующий PHP-скрипт с нуля, который выполняется от начала до конца. Когда приходит новый запрос на порт 8888, относительно потоков управления, мы находимся в середине нашей Node. Как это понять, чтоб не помешаться? Это как раз то, где событийно-ориентированный дизайн Node. Нам надо узнать некоторые новые понятия, чтобы досконально понять всё это. Мы создаем сервер и передаём функцию в созданный им метод. Всякий раз, когда наш сервер получает запрос, переданная нами функция будет вызываться. Мы не знаем, когда это произойдет, но у нас теперь есть место, где можем обрабатывать входящий запрос. Это наша переданная функция и не имеет значения, определили ли мы её сначала или передали анонимно. Этот принцип называется обратный вызов или callback. Мы передаём в некоторый метод функцию и этот метод исполняет её, когда происходит связанное с методом событие. По крайней мере для меня, это заняло некоторое время, чтобы понять. Просто почитайте блог Felix Geisendörfer снова, если вы всё ещё не уверены. Давайте немного поиграем с этим новым понятием. Можем ли мы доказать, что наш код продолжает работать после создания сервера, даже если нет HTTP-запроса и callback-функция, переданная нами, не вызывается? », когда срабатывает функция onRequest наш callback , а текст «Server has started. » — сразу после запуска HTTP-сервера. Когда мы запустим этот код как обычно, node server. Всякий раз, когда мы делаем запрос нашему серверу через переход по адресу в нашем браузере , в командной строке выводится сообщение «Request received. Объектно-ориентированный асинхронный серверный JavaScript с callback-ми в действии :- Обратите внимание, что наш сервер, возможно, будет выводить «Request received. » в консоль 2 раза при открытии страницы в браузере. Когда callback запускается и наша функция onRequest срабатывает, в неё передаются 2 параметра: request и response. Они являются объектами и вы можете использовать их методы для обработки пришедшего HTTP-запроса и ответа на запрос то есть, просто что-то посылать по проводам обратно в браузер, который запрашивал ваш сервер. И наш код делает именно это: Всякий раз, когда запрос получен, он использует функцию response. Write для отправки текста «Hello World» в теле HTTP-ответа. И последнее, мы вызываем response. На данный момент, мы не заботимся о деталях запроса, поэтому мы не используем объект request полностью. Выбор места для нашего серверного модуля Я обещал, что мы вернёмся к организации нашего приложения. У нас есть код очень простого HTTP-сервера в файле server. Давайте поговорим о том, как сделать server. Это делает нашу локальную переменную объектом, содержащим в себе все публичные методы модуля http. А как создать свой собственный модуль и как его использовать? Давайте выясним это, превратив наш скрипт server. Оказывается, нам не надо менять слишком многое. Создание модуля означает, что нам нужно экспортировать какую-либо функциональность этого модуля в скрипт, который его вызывает. Сейчас функционал нашего HTTP-сервера надо экспортировать, что довольно просто: скрипты, подключающие наш модуль сервера, просто запускают сервер. Сейчас мы можем запустить наше приложение через главный скрипт и он будет делать всё то же самое, что и раньше: node index. До сих пор мы работали только с первой частью нашего приложения: получение HTTP-запроса. Но нам надо что-нибудь с ним делать. В зависимости от URL, запрошенного браузером у нашего сервера, мы должны реагировать по-разному. В очень простом приложении мы могли бы делать это напрямую внутри callback-функции onRequest. Но, как я говорил, давайте добавим немного больше абстракции, чтобы сделать наш пример интереснее. Задание соответствия между разными HTTP-запросами и разными частями нашего кода называется «маршрутизация» «routing», роутинг. Давайте тогда создадим модуль под названием router. Что необходимо для «роутера»? Нам нужно иметь возможность скармливать запрошенный URL и возможные добавочные GET- и POST-параметры нашему роутеру и, с учётом этого, роутер должен определять, какой код выполнять этот код есть третья составляющая нашего приложения: коллекция обработчиков запросов, делающие необходимую работу по определённому запросу. Можно поспорить, должен ли этот код быть частью роутера или сервера или даже своего собственного модуля , но давайте сейчас пока просто сделаем его частью сервера. Вся необходимая нам информация доступна через объект request, который передается в качестве первого параметра нашей callback-функции onRequest. Чтобы интерпретировать эту информацию, нам необходимо добавить кое-какие Node. Модуль url поддерживает методы, которые позволяют нам извлекать различные части URL такие как запрошенный путь URL path и строка параметров запроса query string , а querystring в свою очередь, используется для парсинга строки параметров запроса query string : url. Теперь наше приложение может различать запросы на основе запрошенного пути URL. Это позволяет нам направлять запросы нашим обработчикам запросов в зависимости от пути URL, используя наш роутер. Таким образом, мы можем строить наше приложение RESTful-путём, потому что теперь можем реализовать интерфейс, следующий принципам Идентификации ресурсов смотри статью в википедии для справки. Скоро мы увидим, как всё соединяется вместе. Теперь самое время написать наш роутер. Создаём новый файл под названием router. Давайте сначала посмотрим, как скрепить этот роутер с нашим сервером до того как поместим больше логики в роутер. Нашему HTTP-серверу необходимо знать о роутере и использовать его. Мы могли бы жёстко прописать эти зависимости в нашем сервере, но, так как мы знаем только сложные способы из нашего опыта в других языках программирования, мы сделаем слабосвязанную зависимость сервера и роутера через внедрение этих зависимостей можете почитать или для дополнительной информации. Если мы сейчас запустим наше приложение node index. Передача функций связана не только с техническими соображениями. Относительно разработки программного обеспечения это — почти философия. Просто подумайте: в нашем index-файле мы могли бы передавать объект router в наш сервер и сервер мог бы вызывать функцию route этого объекта. Этим способом мы бы передавали нечто и сервер использовал бы это нечто, чтобы сделать что-то. Эй, роутер, не могли бы вы показать мне маршрут? Но серверу не нужно нечто. Ему нужно только получить что-то сделанное, а чтоб получить уже что-то сделанное, вам не нужно нечто совсем, вам необходимо действие. Вам не нужно существительное, вам нужен глагол. Понимание фундаментальных умозаключений, которые лежат в основе этой идеи, позволило мне действительно понять функциональное программирование. Я понял это, когда читал шедевр Стива Йегге частичный перевод на русский. Это одно из лучших произведений о программировании, которое я когда-либо имел удовольствие встречать. Роутинг реальных обработчиков запроса Вернёмся к делу. Наш HTTP-сервер и наш роутер запросов сейчас — лучшие друзья, и общаются друг с другом так, как мы хотели. «Роутинг» подразумевает, что мы хотим обрабатывать запросы на разные URL по-разному. Прямо сейчас мы закончим с нашим роутером. Роутер не место на самом деле, чтобы делать что-то с запросами, потому что будет плохо масштабироваться, а наше приложение будет становиться сложнее. Давайте эти функции, в которые направляются запросы, назовём обработчиками запросов. И давайте возьмёмся за них сейчас, потому что делать что-либо с роутером сейчас пока не имеет смысла. Новая часть приложения, новый модуль — здесь никаких сюрпризов. Создадим модуль под названием requestHandlers, добавим болванки функций для каждого обработчика запроса и экспортируем их как методы модуля: function start { console. В этот момент мы должны принять решение: захардкодить использование модуля requestHandlers в роутере или мы хотим ещё немного внедрения зависимостей? Хотя внедрение зависимостей, как и любой другой паттерн, не должен использоваться только ради того, чтобы быть использованным, в нашем случае имеет смысл сделать слабосвязанную пару роутера и обработчиков запроса и, таким образом, сделать роутер действительно многоразовым. Это означает, что нам нужно передавать обработчики запросов из нашего сервера в наш роутер, но это немного неправильно, поэтому мы должны пройти весь путь и передать их в сервер из нашего главного файла, а также — оттуда передавать в роутер. Как мы собираемся передать их? Сейчас у нас есть два обработчика, но в реальном приложении это число будет увеличиваться и меняться. И мы уверены, что не хотим возиться с роутером каждый раз, когда добавляется новый URL + обработчик запроса. Переменное число элементов и каждому соответствует строка запрашиваемый URL? Так, похоже на ассоциативный массив, это наиболее подходящее. Это решение немного разочаровывает тем фактом, что JavaScript не поддерживает ассоциативные массивы. Оказывается в действительности, если нам нужны ассоциативные массивы, мы должны использовать объекты! Об этом есть хорошее введение. Позвольте мне процитировать подходящую часть: В C++ или C , когда мы говорим об объектах, мы ссылаемся на экземпляры классов или структуры. Объекты имеют разные свойства и методы, в зависимости от шаблонов классов , экземплярами которых они являются. Но не в случае с JavaScript-объектами. Итак, значения могут быть строками, числами и т. Хорошо, наконец-то возвращаемся к нашему коду. Мы решили, что мы хотим передать список из requestHandlers как объект и, для того, чтобы достичь слабое связывание, мы хотим внедрить этот объект в route. Начнём с добавления объекта в наш главный файл index. После определения объекта мы передали его в сервер как дополнительный параметр. Соответственно, изменим функцию route в нашем файле router. Хорошо, это всё, что нужно, чтобы связать сервер, роутер и обработчики запроса вместе! При запуске нашего приложения и запроса в браузере, мы можем убедиться, что надлежащий обработчик запроса действительно был вызван: Server has started. Создание ответа обработчиков запроса Замечательно. Вот только если бы обработчики запроса могли отправлять что-нибудь назад браузеру, было бы ещё лучше, правильно? Вспомните, «Hello World», который выводит ваш браузер в запрошенной странице, всё ещё исходит от функции onRequest в нашем файле server. «Обработка запроса» подразумевает «ответ на запросы» в конце концов, поэтому необходимо дать возможность нашим обработчикам запроса общаться с браузером так же, как это делает функция onRequest. Как делать не надо Прямой подход, который мы захотим использовать как разработчики с опытом в PHP или Ruby, на самом деле ложный: он может прекрасно работать, иметь большой смысл, а потом, когда мы этого не ждём, неожиданно всё развалится. Давайте просто сделаем это и тогда увидим, почему это не такая уж и хорошая идея. Мы начнём с обработчиков запроса и заставим их возвращать то, что хотели бы показать в браузере. Нам надо изменить requestHandlers. Также, роутер должен вернуть серверу то, что обработчики запроса вернули ему. Поэтому надо отредактировать router. И самое последнее, но не менее важное, нам нужен рефакторинг нашего сервера, чтобы заставить его отвечать браузеру с контентом обработчиков запроса, возвращаемых через роутер. OK, тогда в чём проблема? Короткий ответ: потому что мы столкнемся с проблемами, если один из обработчиков запроса захочет использовать неблокирующую операцию в будущем. Подробный ответ займёт немного больше времени. Блокирование и неблокирование Как было сказано, проблемы будут возникать, когда мы добавим неблокирующие операции в обработчики запроса. Давайте сначала поговорим о блокирующих, а потом уже о неблокирующих операциях. Вместо того, чтобы объяснять, что такое «блокирование» и «неблокирование», давайте продемонстрируем себе, что произойдёт, если мы добавим блокирующую операцию в наши обработчики запроса. Для этого модифицируем обработчик запроса start так, чтобы он ждал 10 секунд до того как вернёт свою строку «Hello Start». В JavaScript нет такой штуки как sleep , поэтому мы будем использовать хитрый хак. Наш новый подход заключается в следующем: вместо доставки контента серверу мы будем сервер доставлять к контенту. Чтобы быть более точным, мы будем внедрять объект response из серверной callback-функции onRequest через роутер в обработчики запроса. Обработчики смогут тогда использовать функции этого объекта для ответа на сами запросы. Вот — пошаговый рецепт изменения нашего приложения. Начнём с нашего server. Кроме того, мы удалили всякие вызовы методов response из обработчика onRequest , потому что мы рассчитываем, что route позаботится об этом. Если обработчик запроса не может быть использован, мы заботимся об ответе с надлежащим заголовком «404» и телом ответа. И последнее, но не менее важное, мы модифицируем requestHandlers. Обработчик start будет отвечать изнутри анонимного обратного вызова exec , а обработчик upload будет всё ещё выдавать «Hello Upload», но теперь посредством объекта response. Если вы запустили наше приложение снова node index. Сделаем что-нибудь полезное До сих пор мы делали всё прекрасно и изысканно, но мы не создали ничего значимого для клиентов нашего супер-сайта. Наш сервер, роутер и обработчики запроса находятся на своих местах, таким образом, теперь мы можем начать добавлять контент на наш сайт, который позволяет нашим пользователям выбирать файл, загружать его и просматривать загруженный файл в браузере. Для простоты будем полагать, что через наше приложение будут загружаться и показываться только файлы картинок. OK, давайте шаг за шагом, но с разъяснением больших техник и принципов JavaScript, и в то же время, давайте немного ускоримся. Автору слишком нравится слушать самого себя. Я выбирал этот подход по двум причинам. Во-первых, обрабатывать базовые POST-запросы относительно просто в Node. Во-вторых, обработка загрузки файла к примеру, multipart POST-запросы это не так просто в Node. Обработка POST-запросов Давайте сделаем попроще: предоставим текcтовое поле, которое может быть заполнено пользователем и отправлено на сервер в POST-запросе. После получения и обработки этого запроса мы отобразим содержимое текстового поля. Вы должны увидеть эту очень простую форму, когда запросите в вашем браузере. Если это не так — возможно, вы не перезагрузили приложение. Я уже слышу вас: помещать содержимое представления прямо в обработчик запроса некрасиво. Тем не менее, я решил не включать этот дополнительный уровень абстракции то есть, разделение представления и логики в наш учебник, потому что, я думаю, что это не научит нас чему-нибудь стоящему в контексте JavaScript или Node. Теперь, когда мы стали экспертными новичками, мы уже не удивляемся тому факту, что обработка POST-данных делается в неблокирующей манере, через использование асинхронных callback-ов. Это имеет смысл, потому что POST-запросы могут быть потенциально очень большими — ничто не мешает пользователю ввести текст размером в несколько мегабайтов. Обработка всего массива данных за один раз может привести к блокирующей операции. Чтобы сделать весь процесс неблокирующим, Node. Эти события — data когда приходит новая порция POST-данных и end когда все части данных были получены. Это делается путём добавления слушателей listeners в объект request, который передаётся в нашу callback-функцию onRequest, когда HTTP-запрос получен. В основном, это выглядит так: request. В настоящее время мы можем получить доступ к объекту request только в нашем сервере — мы не передаём его в роутер и в обработчики запроса, как делаем это с объектом response. На мой взгляд, это работа HTTP-сервера — предоставлять приложению все данные из запросов. Поэтому я предлагаю обрабатывать POST-данные прямо в сервере и передавать конечные данные в роутер и обработчики запроса, которые сами решат, что с ними делать. Таким образом, идея — в том, чтобы поместить обратные вызовы событий data и end в сервер, собирать все куски POST-данных в data и вызывать роутер при получении события end, пока идёт передача собранных порций данных в роутер, который в свою очередь передаёт их в обработчики запроса. Мы также передаём POST-данные в роутере, потому что они нам понадобятся в обработчиках запроса. Добавление логирования в консоли для каждой порции полученных данных — возможно, плохая идея для конечного кода мегабайты POST-данных, помните? Я предлагаю немного поиграться с этим. Поместите в текстовое поле сначала немного текста, а потом больше, и вы увидите, что для больших текстов обратный вызов data действительно вызывается несколько раз. Давайте добавим ещё больше крутизны в наше приложение. Чтобы сделать это возможным, нам необходимо передавать postData в обработчики запроса. И последнее по этой теме: то, что мы передаём в роутер и обработчики запроса, является полным телом нашего POST-запроса. Мы, вероятно, захотим использовать индивидуальные поля, составляющие POST-данные, в нашем случае значение поля text. Обработка загрузки файлов Давайте примемся за последний пункт нашего списка задач. Мы планировали дать возможность пользователям загружать файлы картинок и отображать загруженные картинки в браузере. В 90-х это могло бы быть квалифицировано как бизнес модель для IPO, сейчас же этого достаточно, чтобы научить нас двум вещам: как установливать внешнии библиотки Node. Внешний модуль, который мы собираемся использовать, node-formidable от Felix Geisendörfer. Этот модуль поможет нам абстрагироваться от мерзких деталей парсинга входящих файловых данных. В конце концов, обработка входящих файлов это не что иное, как «просто» обработка POST-данных, но, в действительности, дьявол кроется в деталях, поэтому в нашем случае имеет смысл использовать готовое решение. Чтобы использовать код Феликса, соответствующий модуль Node. Он позволяет нам инсталировать внешние модули Node. С учетом установленного Node. Если вы в конце увидели следующее: npm info build Success : formidable 1. Всё, что нам надо — это создать новый экземпляр объекта IncomingForm, который является абстракцией отправленной формы и может быть использован для парсинга объекта request нашего HTTP-сервера, для полей и файлов, отправленных через эту форму. Давайте сначала решим последнюю задачу: если имеется файл картинки на вашем локальном диске, что сделать, чтобы передать его браузеру? Мы, очевидно, собираемся считать содержимое этого файла в наш Node. Конечно же, имеет смысл в первую очередь поместить реальную png-картинку в этот каталог. Мы собираемся изменить requestHandlers. Первый шаг — простой. Давайте просто сделаем это в файле requestHandlers. Следующий шаг — немного более сложный, конечно. Первая проблема следующая: мы хотим обрабатывать загрузку файлов в нашем обработчике запроса upload, и тут надо будет передать объект request при вызове form. Но всё, что у нас есть — это объект response и массив postData. Похоже, что придётся передавать каждый раз объект request из сервера в роутер и обработчик запроса. Может быть, имеется более элегантное решение, но этот способ может делать работу уже сейчас. Давайте полностью удалим всё, что касается postData в нашем сервере и обработчиках запроса — он нам не нужен для обработки загрузки файла и, мало того, — даже создает проблему: мы уже «поглотили» события data объекта request в сервере, а следовательно, form. Да, мы придерживаемся действительно простых вещей и принимаем, что могут загружаться только PNG-картинки. Имеется небольшая дополнительная сложность в логике переименования: Windows-реализации Node. Давайте добавим в requestHandlers. Перезапускаем сервер, и последний пункт нашей задачи реализован. Выбираем локальную PNG-картинку с диска, загружаем на сервер и видим её на нашей веб-страничке. Выводы и перспективы Поздравляю, наша миссия выполнена! Мы написали простое, уже полностью готовое web-приложение на Node. Мы поговорили о server-side JavaScript, функциональном программировании, блокирующих и неблокирующих операциях, callback-ах, событиях, обычаях, внутренних и внешних модулях и о многом другом. Конечно, имеется много вещей, которые мы не обсудили: как общаться с базой данных, как писать unit-тесты, как создавать внешние модули, с возможностью инсталяции через NPM или даже что-нибудь простое, например, как обрабатывать GET-запросы. Но это судьба каждого учебника, предназначенного для начинающих — нельзя расказать о всех аспектах во всех деталях. Хорошей новостью является то, что Node.