Node.js не подходит для типовых веб-проектов

https://coderwall.com/p/diokxg
  • Перевод


«Node.js не подходит для серьезных сайтов и веб-приложений, а только для написания небольших API».
This is bull*hit. I have to say it.

От переводчика: недавно на coderwall.com появилась интересная статья от Ionut-Cristian Florescu об использовании Node.js для создания обычных («типовых») веб-проектов. До ее прочтения я был полностью согласен с заголовком статьи, но сейчас мое мнение несколько поменялось. Позиция автора может быть спорной во многих моментах, но его аргументы достаточно интересны. Если у вас есть собственное мнение по этому поводу, оставляйте его в комментариях.

Я слышал эти слова так много раз, что они уже надоели мне до смерти. В основном они исходят от людей, которые никогда не использовали Node.js ни для чего кроме воспроизведения базового todo-туториала, от «псевдо-разработчиков» или «умников», которые любят читать о том, что сейчас в тренде, но сами не разработали ничего серьезного.

Но кроме них есть дивный новый мир, где судя по всему считают иначе. Такие ребята, как Klout, Geeklist, Transloadit, Cloud9, и многие другие, представленные на этой странице.

Неужели все они ошибаются?
Но все же, откуда взялся этот необоснованный миф?

Устаревшие данные


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

Язычники против неверных


Во-вторых, веб-разработка и языки программирования — это почти всегда объекты религиозного поклонения, и множество людей в этих областях не считают JavaScript «настоящим» языком программирования. Что ж, возможно он не идеален, однако достаточно хорош для того, чтобы быть самым распространенным языком в Интернете на данный момент.

«Callback hell»


Большинство Node.js-разработчиков должны знать, что из-за событийно-ориентированной природы довольно сложно на Node.js делать вещи, требующие последовательного выполнения. По моему мнению, это, возможно, является самой большой слабостью и в то же время самой сильной стороной Node.js. Сильной, потому что, если вы знаете свой инструмент, это закладывает основу для обработки невероятного количества одновременных подключений, возможно на порядок больше, чем вы могли бы получить, используя PHP, .NET или RoR. Слабостью, потому что большинство людей по праву стремятся избавиться от подобного кода:



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

Хорошей новостью является то, что есть достаточное количество весьма элегантных способов сгладить эту проблему: Async.js вероятно наиболее известен, но если вы используете CoffeeScript вы определенно должны рассмотреть следующий шаг к «простой и мощной оптимизации управления асинхронными потоками» с IcedCoffeeScript. Я не уделил ему много внимания, когда впервые обратился к Node.js некоторое время назад, но сейчас, после использования в нескольких проектах, я действительно могу себе представить код без await и defer. Я считаю это идеальным решением для большинства наиболее распространенных сценариев использования, когда у вас есть либо ряд последовательных операций, либо комбинация последовательных и параллельных задач:



Экосистеме Node.js не хватает такого фреймворка, как Rails


Оставив позади проблемы языка/платформы, скажу что это также ложный миф. Лично я люблю Ruby и Rails, но я нахожу их несколько избыточными для небольших и средних веб-проектов, и мне нравится быть настоящим хозяином моего кода. Я предпочитаю начинать с маленькой управляемой кодовой базой и расширять ее, добавлять модули если они мне нужны и когда они мне нужны. Поэтому я считаю, что Express.js предоставляет идеальный баланс между легковесностью и расширяемостью. А Connect, (на котором Express построен) предоставляет вам все возможности Rack, с, осмелюсь сказать, даже более богатой экосистемой. Я знаю, что большинство сравнит Express с Sinatra, но я думаю, что Express — это нечто большее, кроме того, я слышал, что даже хардкорные рубисты признают, что Rails временами слишком избыточна.

Но если вы применяете Node.js и вам импонирует Rails, возможно вам стоит обратить внимание на Tower.js или Geddy.

Пакеты, управление подключаемыми файлами


Конечно же, в мире Node.js нет ничего сравнимого со Sprockets? Вообще-то есть. И не одно. Node.js это место где появляются и такие вещи. Bower, Brewer.js, Piler, — вот имена только некоторых из них.
UglifyJS Mihai Bazon'а также работает на Node.js.
Trevor Burnham, автор «CoffeeScript: Accelerated JavaScript Development» написал connect-assets, который сейчас поддерживается Andrew Dunkman'ом.
Для разработчиков, которым нужна простая, но не менее мощная альтренатива, я несколько месяцев назад выложил в open-source ASPA и ASPA-Express.
Таким образом, здесь есть из чего выбрать.
Как обстоят дела с шаблонизаторами? Их также достаточно, лучшие по моему мнению Jade и Stylus.

Скорость и параллелизм это еще не все


Нет, скорость и параллелизм это не все, но они чертовски важны. Я слышал, что многие говорят: «Я пока буду использовать PHP / .NET / Ruby, а если посещаемость моего сайта вырастет до тысяч посетителей в день, я просто увеличу количество серверов».

Но, по-видимому, это проще сказать, чем сделать. Даже GitHub порой имеет проблемы — уверен, что многие время от времени видели раздражающую страницу с ошибкой unicorn’а.

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

Также, мне доводилось, слышать о сайтах, которые просто «положили» поисковые роботы Google. И вы конечно же не хотите, чтобы подобное случилось с вами, потому что на данный момент в онлайн-бизнесе, если Google не является «вашим другом», то вас просто не существует.

Таким образом, возможность обрабатывать большие объемы траффика без потери скорости сайта никогда не будет лишней. Особенно, если вы при этом не должны платить большие суммы за инфраструктуру и поддержку (никто не будет писать это на чистом C).

Нехватка хороших Node.js-разработчиков


Т.к. Node.js основан на JavaScript, он привлек много веб-разработчиков с «отсутствием надлежащего опыта серверной разработки»(т.е. не знакомых даже с основными шаблонами проектирования). Хотя это и верно в некоторой степени, но я думаю, что большинство новичков все же будут держаться подальше от Node.js.

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

Большие корпорации пока не используют Node.js


Отлично. Большие корпорации используют .NET и J2EE, по крайней мере в моем мире. Если вы хотите оказаться там, придерживайтесь .NET и J2EE, регулярно посещайте семинары Microsoft и Oracle, и возможно даже вам стоит присмотреться к Scala.

Это всего лишь мое мнение. Оно не является неизменным, но я по крайней мере могу сказать, что оно обосновано; на протяжении моей карьеры я писал код на C#, Java, PHP, Ruby, JavaScript и не только. Я работал над «серьезными» бизнес-приложениями и мне также удалось выжить как частному предпринимателю не в сфере информационных технологий, так что я научился смотреть на мир не через призму IT. Но процесс кодинга определенно стал приносить гораздо больше удовольствия, когда я открыл для себя Node.js.

Исходя из всего этого, у меня не возникло сомнений при выборе Node.js, когда я заново переделывал LeasingSH.ro, известный в Румынии сайт по продаже автомобилей. Это не большой проект, но это как раз тот самый типовой веб-проект, о котором мы говорим:



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



Код также стал более читаемым и поддерживаемым, т.к. использование новой технологии косвенно привносит и новые особенности (в противоположность старому PHP), такие как использование BitBucket для управления исходным кодом, более четкое разделение задач — в основном за счет использования шаблонов Jade, эффективного сжатия и управления подключаемых файлов с ASPA.

И в заключение, хотелось бы видеть больше типовых веб-проектов, выполненных на Node.js. Слишком многие из них по-прежнему реализованы на PHP. Не поймите меня неправильно, я использовал PHP несколько лет и я не против него, но иногда нам нужно смотреть в будущее.
Поделиться публикацией

Похожие публикации

Комментарии 178
    +11
    Зачем же размещать примеры кода в виде картинок, да ещё и с перспективой? Глаза же сломать можно.
      +37
      Вам, очевидно, хотят показать не конкретный код, а то, что вы видите, если не всматриваетесь в него. Общий внешний вид, успешно передающий в чертах принцип построения и структуру.
        0
        Ну, это не переводчик придумал, оно и в оригинале так. А вот у автора оригинала — инстаграм головного мозга.
          0
          я только из-за «ванильных» картинок с кодом и лайкнул пост :)
          0
          Заметно уменьшилось время отклика?
            +1
            да, вы правы конечно же, спасибо.
            +13
            Я не програмист javascript вообще. Вопрос у меня очень практический: есть ли клон вордпресс/джумлы на node.js и есть ли вики на node.js?
              –5
              GOOGLE:
              1.NODE.JS MODULES nodejsmodules.org/tags/wordpress
                +11
                Я умею пользоваться, Ваша сыылка выдает МОДУЛИ. Перечитайте, пожалуйста, вопрос.
                  0
                  Пропустил слово клон?
                +5
                А зачем? Для вордпресса есть вордпресс, для джумлы — джумла. PHP и Node могут спокойно жить рядом.
                  0
                  Автор статьи делает упор на скорость. Допустим, я согласен. Вордпресс — типовая блогоплатформа для php, joomla — типовая cms. Какой ответ дает нам node.js в этой нише? Искренне надоела неспешность php сайтов. Да, я знаю как готовить php, не надо развивать эту тему. Хочется какой дейсвенный ответ-замена на node.js
                    +12
                    Никакую, по крайней мере пока. Это не так плохо: до тех пор пока на ноде нет вордпресса и джумлы никто не обзывает его неспешным. :)
                      +10
                      Значит node.js не подходит для типовых веб-сайтов, по крайней мере пока. Спасибо.
                        +2
                        Это всего-навсего значит что node.js не подходит для ваших типовых проектов.

                        Что же вы так по себе всех разработчиков ровняете? «Типовые проекты» — они разные бывают. Для кого-то «типовой проект» — это сайт-визитка на Юкозе, и он даже после появления вордпреса/джумлы на ноде будет говорить «Значит node.js не подходит для типовых веб-сайтов».
                          +3
                          Вы ориентируетесть на тот факт, что кто-то не написал еще CMS похожую на wordpress? Тогда PHP тоже не подходил для «типовых сайтов» пока не было Wordpress. Такая ваша точка зрения?
                            +1
                            Грубо говоря, да, не подходил. Не было разницы разрабатывать типовой сайт или не типовой, максимум можно было сократить срок разработки копипастом свох наработок из предыдущих проектов в новые. PHP или Perl (а в отдельных случаях и C/C++) тоже особого значения не имело.

                            Появление FOSS проектов типа Wordpress или Joomla (я бы вспомнил прежде всего о PhpNuke и PhpBB первых версий — умерли, но заметный след в методологии оставили) изменило само представление о критериях подходящести той или иной платформы для типовых сайтов.
                              0
                              Согласитесь такая точка зрения, скорее подходит к локальному мнению. То есть, ВАМ не подходит. Что воовсе не означает, что на Node.js не стоит делать какой-нибудь бложик или магазин. Или сделать вменяемую CMS.

                              Все же в глобальном значении «неподходит для типовых сайтов», означает, что с помощью этой штуки, явно не следует делать «тривиальные сайты». Вот 1С не подходит для типовых сайтов (не очень пример, да).
                                +2
                                Я вообще давно не занимаюсь типовыми сайтами. Но если придется создавать визитку или магазин, то выберу популярную CMS с открытым кодом, большим и активным сообществом, множеством готовых модулей и тем, доступную для разворачивания любым эникейщиком, а то и секретаршей на практически любом дешевом хостинге. Как думаете, много у меня альтернатив? И какие из них написаны на Node.js?

                                А для разработки типового сайта разрабатывать вменяемую CMS это как для поездок на работу разрабатывать свой автомобиль. Вот будет кем-то написана вменяемая CMS на Node.js, тогда можно будет задуматься об использовании. Или хотя бы разработка типовых сайтов будет составлять основную бизнес-задачу (типовая веб-студия) — тогда можно разработать свою, если платформа даёт какие-то реальные преимущества перед CMS на других платформах.
                        +1
                        Из статьи вроде вполне понятно, что речь идет о _разработке_ типовых веб-приложений на node.js.

                        Если вы разработчик, то как система разработки веб-приложений Node.js вполне адекватна. Все инструменты для нормальной разработки есть…
                        Если вы аникейщик, желающий развернуть бложик в два клика, то тут не о вас речь. Обращайтесь к разработчикам, они вам сделают «как в вордпрессе»…
                          0
                          Инструменты есть, но есть ли необходимый набор библиотек/фреймворков, чтобы реализовать типовые функции типового сайта не одним кликом, а парой-тройкой строчек кода?
                            0
                            Подозреваю (но априорно), что могут быть готовые модули.

                            А которые типовые функции?

                            Перечислите, пожалуйста.
                              0
                              Основная — создание и редактирование в «админке» страниц для сайта в режиме WYSIWYG с полуавтоматическим (редактирование сгенерированного автоматически) включением её в основное иерархическое меню. Естественно управление пользователями админки в админке хотя бы на уровне http autentication. Желательно гибкое управление правами с использованием групп, ролей и прочих ACL. Большое количество различных модулей типа голосовалок, оценок, обратной связи, комментариев, статистики, рекомендаций, «также интересуются», курсов валют, погоды и т. п. Хотя бы простейший интернет-магазин с инттеграцией с системами онлайн-оплаты. Простая, не требующая знаний html/css/js возможность темизации и кастомизации готовых тем, включая редактирование раскладки модулей.

                              Это так, на вскидку.
                          0
                          Тут все просто, — для Wordpress и для vBulletin пока нет ни единой адекватной замены в мире Rails, Django, не говоря уж о Node, Go, JEE.
                        0
                        Вики есть несколько, что считать клоном вордпресса — вопрос открытый (бложиков много разных, но они, конечно, не совместимы с WP).
                          +1
                          Есть проект, альтернатива wordpress — Ghost. Проект успешно профинансирован на кикстартере, собрали около 200тыс. фунтов. Очень много положительных отзывов. И проект написан как раз таки под node.js.
                            +3
                            Ещё не работает и код ещё не открыт.
                          –6
                          Вордпресс и джумла — CMS системы, на уровне языка у них PHP, когда node.js — фреймворк. Уровень абстракции несколько выше чем у CMS.
                            +6
                            node.js не больший фреймворк, чем php.
                              +2
                              node.js позволяет ботать на более низком уровне.
                                +1
                                Считаете, что фреймворк — это нечто низкоуровневое по сравнению с ЯП?
                                  +1
                                  На каком? Прямое обращение к памяти и портам? Или средства создания нативных приложений и библиотек из коробки? А так что-то в голову не приходит, что не может сделать PHP из того, что может Node.js в частности и JavaScript вообще.
                                    0
                                    Думаю, имеется в виду обвязка веб-сервера. Не то, что бы это более низкий уровень, я бы это назвал «больше возможностей».
                                      0
                                      PhpDaemon вроде аналог Node.js для PHP.
                                +4
                                Што?
                                0
                                Меня несколько удивляет ваш вопрос. Вот возьмём java — можно нагуглить цмски, но ими почти никто не пользуется (хотя конечно есть всякте ecm вроде alfresco, но это другое).

                                Это в мире php актуально знать именно cms, в java/c#/node js актуально знать фреймворки. Про руби и пайтон не скажу, но по-моему там так же правят бал фреймворки, а не cms.

                                Я не удивлюсь, если в мире node js вообще никогда не появятся сколько-нибудь серьёзные cms.
                                  +1
                                  Иронично, что автор статьи пытается донести мысль обратную Вашей. Он как раз настаивает что node.js подходит для типовых проектов. В моем понимании блог и cms — просто классика из классики типовых веб проектов. На фоне заявленной скорости и мощного фунуционала удивительно что нет реализации сколь нибо сильной алернативы. Alfresco как раз удачный пример из мира Java.
                                    0
                                    Я не утверждаю обратного, сам пишу под node, как могу.

                                    Знаете, я пожалуй соглашусь с вами, правда от части — блог, визитки, магазины — вот типовые проекты интернета на мой взгляд.
                                    Подходит ли для них Node? Да, безусловно. Вот в php есть YII, к примеру. Аналоги в этой нише у нода есть, на мой взгляд этого вполне достаточно. Создана вся необходимая инфраструктура (не буду повторять автора статьи, перечисляя).

                                    Другое дело что веб-студии, работающие в сфере дешевых сайтов (5-25 т.р.) вряд ли когда нибудь перейдут на нод — стоимость разработки будет значительно выше, чем cms-based сайтов.
                                    Короче в этой сфере конкурировать с cms не получится. Впрочем те же джависты и дотнетчики сюда не лезут. Ту же альфреску на моей памяти разворачивали индивидуально под клиента и долго пилили. Да и никогда не видел личного блога на альфреске. Впрочем это мой персональный опыт.
                                      0
                                      Типовый проект — это не CMS, а все-таки сайт, построенный на CMS. Необходимость доработки напильником не меняет сути проекта.

                                      Скажем, я поднял достаточное количество типовых проектов на Python/Django, и ни один из них не был сделан на готовом «движке» вроде WordPress. Этот факт не делает унылые бложики менее типовыми, не делает процесс их развертывания сложнее, т.е. вообще ничего не меняет. Просто немного отличается подход.
                                        0
                                        То есть поднятие бложика на джанге требует не больше усилий (времени) чем бложика на WordPress? И большей (не просто другой, а именно большей) квалификации тоже не требует?
                                          0
                                          Требует, почему не требует. Это компоненты стоимости, не более того.

                                          А как стоимость проекта коррелирует с его классификацией? По-моему никак.

                                          Типовый айфон стоит несколько дороже, чем типовая нокия-3310, в его производстве (вероятно) участвуют более квалифицированные китайцы, но это не меняет сути товара ширпотреба.
                                            0
                                            С классификацией — никак. С подходящестью платформы — один из основных критериев, если не единственный основной. Можно бложик и на ассемблере написать — подходит ли ассемблер для бложиков?
                                              0
                                              «Подходящесть» платформы — это функция рынка.
                                              Есть ли потребность в бложиках на ассемблере? Нет. Значит, ассемблер для бложиков «не подходит».
                                              То же самое на Node.js? Есть, за это платят деньги. Значит, Node.js (Django, Ruby, вставить нужное) подходит.
                                              Как-то так.
                                                0
                                                Если заказчик платит за результат, то часто ли есть экономический смысл за фиксированную сумму использовать для типового проекта Node.js, RoR, Django, Symfony и т. п., а не взять «готовую» CMS? А если есть, то не окажется ли такие случаи сильно выходят за рамки типового проекта?
                                                  0
                                                  Это имеет сразу несколько экономических смыслов: повторное использование существующих наработок, стоимость поддержки и доводки напильником, не в последнюю очередь job security.

                                                  По моему опыту, около 100% сайтов выходят за рамки типового проекта. (Выборка нерепрезентативна.)

                                                  На WP классно сажать школьников лепить дорвеи — взял бесплатный шаблон, алгоритм Маркова для текстов, SEO-плагин, тяп-ляп — готов сайт. Доработка WP до чего-то концептуально отличающегося — это боль и унижение. В такой ситуации (которая нередко возникает в самом конце проекта / на стадии поддержки) Django становится дешевле и привлекательнее, см. выше.

                                                  Страховаться от внезапных «доделок» железобетонным техзаданием тоже не всегда выход.
                                    0
                                    По поводу вашего вопроса:
                                    github.com/joyent/node/wiki/modules#wiki-content-management

                                    Это список cms на nodejs. Естественно они ещё не на том уровне, как вордпресс или друпал, т.к. они значительно моложе
                                      0
                                      Ghost вроде как. Он по моему даже многопользовательский. Есть еще Calipso CMS.
                                      Это их того о чем я слышал.
                                      +1
                                      Сайт, который приведен в статье, действительно работает очень шустро.
                                      Заметил, что в исходном коде страницы вырезаны пробелы и переносы строк — это сделано просто так или тоже для оптимизации?
                                        +5
                                        я не автор и сказать точно не могу, но думаю, что упомянутый автором Jade при компиляции шаблонов их просто не вставляет
                                          +1
                                          У него есть два режима: стандартный (без пробелов-переносов) и pretty-print (с ними). Очевидно, на время разработки включался pretty-print, а потом все работало уже в стандартном режиме.
                                          +26
                                          Вот только не очень понятно, почему уменьшение скорости отклика автор приписывает именно переходу на Node, а не, например, ряду оптимизаций, которых он мог провести при переписывании кода «с нуля».
                                            +4
                                            просто автор еще не открыл для себя nginx
                                              0
                                              Вполне вероятно, что в процессе перехода от PHP случился также переход от стандартного для многих LAMP к чему-нибудь более лёгкому и быстрому.
                                              +3
                                              А меня смущает что на php страницы генерились по 600-800мс, ведь страницы там не очень сложные.

                                              Очевидно же, что дело не в языке программирования, а в избыточной и плохо настроенной cms. Если переписать на php с ноля не используя cms, то время сократилось бы до 10-30мс на выделенном то сервере.

                                              Дайте мне этот сайт и я перепишу его на php так, что бы он работал быстрее чем на node.js
                                                0
                                                Я для себя сравнивал PHP и Node.JS в плане производительности — простые скрипты работают приблизительно одинаково. Однако node.js может работать быстрее из-за отсутствия блокировок потока при доступе к ресурсу. Пока поток ждет ответа от базы — он спит и сервер выделяет ресурсы для другого потока. Как только ответ получен — поток запускается и продолжает выполнение. PHP так не может делать. Но я думаю, что это все равно не дает какого-то серьезного преимущества.
                                                  0
                                                  Такая асинхронность не уникальна для Node.js. Спеки servlet 3.0 для Java предлагают аналогичное
                                                    0
                                                    Да и в асинхронном стеке ASP.NET 4.5 это уже есть. Только в отличие от node.js в рамках одного процесса работают несколько воркеров, являющихся тредами из стандартного пула. Подозреваю, что абсолютно точно так же сделано и в яве.
                                                    0
                                                    только не потока, а клиентского запроса, поток-то как раз один обрабатывает все запросы, из-за этого и проблемы в основном
                                                    –1
                                                    Дайте мне этот сайт и я перепишу его на php так, что бы он работал быстрее чем на node.js

                                                    Ну это то вряд ли :) При прочих равных, V8 делает PHP по скорости исполнения как Тузик грелку (в большинстве случаев). С ростом нагрузки этот разрыв в перфомансе только увеличивается (впрочем, вопросы масштабирования не так важны для «типовых веб-сайтов»).
                                                      +4
                                                      Пока самый приближенный к реальности тест из которых я видел: www.techempower.com/benchmarks/#section=data-r6&hw=i7&test=query

                                                      И ситуация там с точностью наоборот.

                                                      Кстати, тест opensource, можно смотреть как все работает, фиксить.

                                                      P.S.
                                                      Если уж затачивать все хардкорно на скорость, можно писать сразу под hiphop vm — будет ближе к cpp, в новой версии теста обещают hiphop vm добавить.
                                                    0
                                                    Да он на любой технологии не должен сильно долго работать при продаваемых на данный момент 3500 автомобилях. Думаю, трафик там соответствующий.
                                                    –1
                                                    Ну уж не знаю, не знаю. Всё же использование async уже подразумевает замедление работы, поэтому я бы рекомендовал весь highload придерживаться назначению nodejs. Пока в коде возникают велосипеды при разработке обычных проектов, которые при нагрузке проявят себя.
                                                      +4
                                                      Замедление при использовании async? С одной стороны, вы конечно же правы. С другой стороны, это трудно назвать задержками, на фоне хотя бы одного запроса к бд.
                                                      Точно так же можно «экономить» на уменьшении кол-ва вызываемых функций. И уж ни в коем случае не использовать наследование и классы.
                                                        0
                                                        Задержки есть, можете проверить на большом количестве одновременных подключений. Я же уточнил, что для highload требуется придерживаться RIA для обычных приложений, если не планируется в дальнейшем их переписывать под нагрузку.
                                                          0
                                                          Хочу у Вас спросить, как бы Вы реализовали конструктор, чтобы его можно было вызывать с new и без него, и при этом передавался экземпляр? Если вы ответите, я на 100% уверен, что могу предоставить код, который будет производительнее вашего на ~60%.
                                                            0
                                                            Если откинуть замер члена, то к чему ведёте?
                                                              0
                                                              Вы обращаете внимание на замедление библиотек таких как async.js, но сами не соблюдаете быстродействие своего кода.
                                                              0
                                                              А я бы в любом случае посмотрел бы на ваше решение — очень интересно.
                                                                +5
                                                                  +3
                                                                  Чем это решение отличается в лучшую сторону от самовызывающегося конструктора Джона Резига в форме без arguments.callee, которая имеет такой вид:

                                                                  var имяКонструктора = function(arg1, arg2, arg3){ // ← набор аргументов (три для примера)
                                                                     if(!( this instanceof имяКонструктора )){
                                                                        return new имяКонструктора(arg1, arg2, arg3);
                                                                     }
                                                                     // далее следует основное тело конструктора
                                                                  };
                                                                  
                                                                    0
                                                                    Ну там же по ссылке все есть. Оно отличается а) кодом б) производительностью.
                                                                      0
                                                                      1. Оптимизация касающееся конструктора K, он вынесен из «цикла» инициализаций объекта и определен в памяти только 1 раз. Да еще и его prototype указывает на prototype конструктора.
                                                                      2. Оптимизация касающееся переменной self, она определена в памяти, но не задействована до момента определения контекста. Многие сделали бы так:
                                                                      var self = this;
                                                                      if (!(this instanceof Ctor))
                                                                        self = new K();
                                                                      

                                                                      3. И самая главная часть. Конструктор не вызывается из себя (КО). Т.к при вызове конструктора Ctor сохраняются все аргументы в памяти, плюсом утечкой становится вызов этого же конструктора. Т.к при инициализации объекта через new, создается пустой объект:
                                                                      var instance = {}

                                                                      Устанавливается prototype этому объекту с ссылкой на prototype конструктора:
                                                                      instance.prototype = Ctor.prototype; 

                                                                      Да и еще и вызывается повторно через apply:
                                                                      var ctor = Ctor.apply(instance, arguments);
                                                                      

                                                                      В итоге, у нас в памяти весит 2 функции с разными контекстами. Один из которых, просто будет передавать инстанс объекта. Метод же, который предоставил я, отличается тем что в памяти храниться один пустой K конструктор и вызывается без изменения контекста неоднократно, а контекст Ctor просто изменяется на тот же пустой объект с ссылкой на prototype Ctor. В итоге 60% прирост.
                                                                        0
                                                                        Пока писал еще лучше оптимизировал. Теперь прирост на 66%.
                                                                        (function (window) {
                                                                          var L
                                                                            , K = function () {}
                                                                            , document = window.document;
                                                                        
                                                                          var Constructor1 = function () {
                                                                            var self;
                                                                            if (this instanceof Constructor1)
                                                                              self = this;
                                                                            else      
                                                                              self = L;
                                                                        
                                                                            return self;
                                                                          }
                                                                        
                                                                          K.prototype = Constructor1.prototype;
                                                                        
                                                                          L = new K();
                                                                        
                                                                          Constructor1.prototype.pipe = function (data) {
                                                                            return data;
                                                                          }
                                                                          
                                                                          window.Constructor1 = Constructor1;
                                                                        })(this);
                                                                        
                                                                          +2
                                                                          Техника шикарная, но в этом варианте вас уже немножко «понесло», так как здесь Constructor1() === Constructor1() — получили мешанину из инициализатора и синглтона.
                                                                            +1
                                                                            Да, точно. Простите.
                                                                              +1
                                                                              Бывает. «Не ошибается тот, кто ничего не делает» )
                                                                      0
                                                                      Типо мы все равно инициализируемся прямо внутри Constructor1, а возвращаем объект с пустым конструктором, чем исключаем целую еще одну проверку instanceof Constructor1. Умно.
                                                                        0
                                                                          +2
                                                                          Честно говоря, такие примеры разочаровывают в Javascript'е.
                                                                          Я в сомнении, починят ли его когда-нибудь, чтобы подобный код не выглядел как мумбо-юмбо.
                                                                            +1
                                                                            Честно говоря, inook показывает пример такой оптимизации, которая для большинства приложений чрезмерна.

                                                                            Только поэтому такая куча кода.

                                                                            Не судите по ней о JavaScript.

                                                                            Используйте самовызывающийся конструктор Джона Резига, его хватит для большинства приложений.
                                                                          0
                                                                          1. Правильно ли я понимаю, что полезный код придется привести в обоих конструкторах?
                                                                          2. Правильно ли я понимаю, что в зависимости от формы вызова будут получены экземпляры разных классов, что ломает код, который может где-то дальше зачем-то проверять что вернулось? (нет годы под рукой)
                                                                          instanceof (new Constructor1()) === 'Constructor1'; // true
                                                                          instanceof (Constructor1()) === 'Constructor1'; //false
                                                                          

                                                                          А вообще, чем более строгие правила работы с собой диктует функция/модуль, тем более производителен код.
                                                                0
                                                                К сожалению node.js Для меня не подходит по причине того, что сейчас у меня множество наработок на Yii(php), и если переходить на другой язык или фреймворк то я потеряю время, а значит деньги. Я не хочу терять деньги ради самосовершенствования :)
                                                                  +2
                                                                  Выиграв сейчас — проиграешь потом. Продолжай в том же духе.
                                                                    +6
                                                                    Не думаю что это тот случай, я ничего не выиграю.
                                                                      +12
                                                                      Сколько тяжёлых проектов на ноде лично вы написали и запустили?
                                                                      За какой период вам обычно удавалось найти программиста на разработку подобных проектов?
                                                                      Способны ли типичные админы справиться с поддержкой систем на ноде?

                                                                      Нода _может_ подходить для небольших отдельных приложений и для частей сложных приложений, которые тормоооозят, будучи написанными на «классических» серверных языках типа пхп и питона. Но только при условии, что в команде есть хотя бы один человек, которого не будет тошнить от ада роутинга и бесконечных коллбеков. Всё остальное происходит на классических языках.
                                                                        0
                                                                        Согласен с Вами. Нода может быть отличным решением для частей проэкта.
                                                                    +1
                                                                    nodejs.org/api/cluster.html#cluster_cluster

                                                                    «A single instance of Node runs in a single thread. To take advantage of multi-core systems the user will sometimes want to launch a cluster of Node processes to handle the load.»

                                                                    Статус — Experimental (!)

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

                                                                    В статье был пример использования async для параллельного выполнения задач. Пусть это будут запросы к бд, например. Чтобы был прирост производительности от параллельного выполнения, все функции должны быть асинхронные и неблокирующие процесс. Даже с учетом того, что событийная модель реализована во всех драйверах (самый лучший случай!) для nodejs, все эта параллелизация будет выполняться в рамках одного процесса (узла кластера).

                                                                    Есть способ использовать ресурсы всех ядер?..
                                                                      –1
                                                                      Нет практически никакого смысла запускать запросы к бд в разных узлах кластера(ядрах процессора), т.к. основное время уходит на ожидание ответа от бд. Другое дело со сложными мат вычислениями — их логичнее запускать параллельно в разных ядрах. Но сложные вычисления, это не типичная задача для Node.js. А со своей основной задачей — обслуживание большого количества клиентов, node.js справляется вполне удачно.
                                                                      Несомненным плюсом является как раз отсутствие реальной асинхронности, т.к. не приходится заботиться о синхронизации и локах.
                                                                        0
                                                                        Согласен. Тем не менее, привзязанность воркера к одному потоку — это уже верхняя планка.

                                                                        Действительно ли в мире nodejs вообще нет (не предусмотрено/никогда не используются) блокирующих контекст (текущий поток) вызовов? Потому, как я понимаю, учитывая однопоточность, один такой вызов функции может заблокировать весь eventloop внутри воркера.
                                                                          0
                                                                          Блокирующих вызовов в ноде не используется. Заблокировать поток совершенно просто. Достаточно элементарного «while(1){}».
                                                                            +7
                                                                            После непродолжительного поиска попались статьи

                                                                            zef.me/4561/node-js-and-the-case-of-the-blocked-event-loop

                                                                            bitcartel.wordpress.com/2012/05/22/the-node-js-cpu-blocking-thing/

                                                                            В которых также критикуется однопоточность nodejs.

                                                                            По первой ссылке: парсинг 15mb json — 1.5 секунды. В более реальном примере пусть будет 150kb — 15ms.

                                                                            На эти самые 15 ms будут задержаны все ответы клиентам. И не важно сколько в таком случае nodejs будет поддерживать одновременных подключений, чем очень гордится. Я не вижу возможности отделить пул или хотя бы один поток для обслуживания событий запрсов-ответов клиентам. Даже модель кластера из воркеров не будет достаточно эффективна при подходе «по потоку на воркер».

                                                                            Тема кластера nodejs затрагивается по второй ссылке.

                                                                            "...Using Cluster looks simple, but if you’re a conscientious programmer, you now have a few things to worry about. For example “Forking a new worker when a death occurs” or “Monitoring worker health using message passing”. "

                                                                            И после всего, модуль Cluster — экспериментальный!

                                                                            И о какой зрелости проекта, упоминаемой в статье можно вести речь?..
                                                                              +1
                                                                              Для парсинга огромных файлов надо делать отдельную программу, запускать ее и асинхронно ожидать завершения. Тогда ничего блокироваться не будет.
                                                                                +1
                                                                                не цепляйтесь конкретно за парсинг. Все, что я хочу сказать — это то, что любая cpu-intensive задача тормозит работу всего процесса (например, задерживает ответы клиентам)
                                                                                  +1
                                                                                  Это не страшно, потому что можно запустить много процессов-воркеров (например, столько же, сколько процессорных ядер в системе). Так что другие клиенты просто пойдут на другие воркеры.
                                                                                    +2
                                                                                    На это я обратил внимание в комментарии выше.

                                                                                    > Так что другие клиенты просто пойдут на другие воркеры.

                                                                                    Как они пойдут?.. Допустим, это будет round-robin…

                                                                                    Как один нод узнает, что другой выполняет cpu-intensive work и возьмет работу на себя?

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

                                                                                    Вы правда не согласны, что модель пула тредов внутри воркера более эффективна, чем однопоточная сущность nodejs?
                                                                                    Я и сам поклонник async/non-blocking моделей, но не думаю, что это лучше делать на nodejs. Алетернатив достаточно…
                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                                        0
                                                                                        Под воркером я подразумевал cluster node.

                                                                                        Воркеры, упомянутые Вами, похоже на те, что составляют worker queue. Так?

                                                                                        Задача в 10-20 мс достойна выделенной очереди в таком случае?..

                                                                                        «принцип построения асинхронных однопоточников» — даже звучит не очень. эту однопоточность я и подвергаю критике.

                                                                                        Итак, для выноса cpu-intensive задач (еще довольно непонятно когда задача в node.js приобретает этот статус) возможны варианты:

                                                                                        1. worker queue (здесь я подразумеваю и ответ после обработки)
                                                                                        2. fibers — насколько я узнал это расширение возможностей V8. На 80% написана на С/С++. То, небольшое количество кусочков кода, приведенных в документации выглядят, мягко говоря, неуклюже. Сомневаюсь, что большинство вообще его использует.
                                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                                            +2
                                                                                            Единственный контекст, под которым я обобщаю эти 2 понятия, — это вынос тяжелых задач за пределы основного event-loop. Да, эти threads-a-gogo можно считать решением. Хотя я не вижу активное развитие проекта. Код выглядит все также плохо.

                                                                                            Вывод для меня: да, возможно. threads-a-gogo — хороший вариант. Однако, почему-то он не кажется нативным для node.js Еще одно расширение, написанное на C/C++

                                                                                            Когда функционал базового V8, Fibers, Threads-a-gogo, Async объединится в единое решение и, что не менее важно, появится для этого хороший api — я смогу считать Node.js, как платформу, зрелой. Но это лишь будет достижением уровня JVM .NET Go и, может, чего-то другого…
                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                              0
                                                                                              И объясните мне, пожалуйста. Если все-таки решение с потоками возможно для V8 через расширение, в чем смысл запуска eventloop на одном потоке? Почему нельзя его запустить на пуле из потоков (= число процессоров)? Какие у этого подхода недостатки в сравнении с кластером из такого же количества нодов?

                                                                                              Потому что я вижу только преимущества.
                                                                                              Что я упускаю?
                                                                                                0
                                                                                                Threads-a-gogo не использует разделяемой памяти и работает через сообщения. Запустить несколько потоков с разделяемой памятью мешает то же, что и в Питоне, Руби, Пхп — gil.
                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                        0
                                                                                        Любая cpu-intensive задача должна выноситься во внешнюю программу.

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

                                                                                        У меня лично нет предпочтения ни одному из подходов. В случае ноды можно забыть про многопоточность, мютексы, дедлоки, баги, воспроизводящиеся в полнолуние на 13-м сервере, но надо следить, чтобы каждый запрос отрабатывался максимально быстро и все длительные операции были асинхронными. В случае традиционных поточных моделей проще писать код.
                                                                                          +1
                                                                                          И каким образом обычно происходит общение с этой внешеней программой? Система от этого перестает быть проще.

                                                                                          > «В случае ноды можно забыть про многопоточность»

                                                                                          Я люблю многопоточность. Забыть про локи, синхронизацию и т.д. можно и в других, более лучших средах.php

                                                                                          Я программирую под JVM на Scala. Наша небольшая компания ни разу не энтерпрайз, я не посещаю семинары от Microsoft/Oracle, и я не усатый дядька.

                                                                                          Если бы заголовок статьи был «Чем node.js лучше php», я бы ни сказал ни слова. Но не надо критиковать тут неповоротливость платформ JVM и .NET. Реализация событийной модели на них гораздо лучше. Верю, что и с Go дела обстоят также.
                                                                                            0
                                                                                            А где, кстати, говорится про неповоротливость JVM и .NET? Напротив — это самые быстрые VM по скорости исполнения, даже быстрее V8. Вопрос только в том, что и C#, и Java куда более «многословны» для решения задач для веба. Иногда — излишне. А вот PHP — действительно неповоротлив.
                                                                                              0
                                                                                              Вынес из контекста пары абзацев прямо под заголовком «Большие корпорации пока не используют Node.js»

                                                                                              К C# я мало отношения имею. Но частенько пробегают статьи про его асинхронные механизмы.
                                                                                              Тут и комментарий есть
                                                                                              habrahabr.ru/post/191646/#comment_6657790

                                                                                              О Java надо говорить не как о языке, а подразумевать JVM, как платформу со Scala, Clojure… Которые могут быть более элегантны, удобны и менее многословны, чем Node.js
                                                                                                0
                                                                                                Если говорить о java есть еще такая чудесная штука как vertx.io для которой, впрочем можно писать и на js, и на groovy и на многих других языках. Очень реактивная штука.
                                                                                                0
                                                                                                В чём неповоротливость PHP? Не холивара ради, а реально интересно. Какие реальные задачи (в рамках классического HTTP) какого масштаба нужно решать, чтобы увидеть качественную разницу? Сложность разработки и многословность опустим для ясности.
                                                                                                  0
                                                                                                  tl;dr: Видно при большом количестве одновременных посетителей, и при достаточно CPU-интенсивных задачах перед выводом результата.

                                                                                                  Long story. Задачи, которые мы решаем — интранет-решения средней и высокой сложности, от большого количества стандартных CRUD до нестандартных операций, большого количества взаимодействия с помощью Ajax и большого количества read-операций, зачастую с объединением данных из разных источников в памяти.

                                                                                                  Вкратце о выводах — проводили специальные, исходящие из задач бенчмарки на голую отдачу рассчитанных значений, операций объединения списков, операций, сильно завязанных на I/O (база данных и файловая система), общая производительность фреймворков в целом (PHP Slim/Yii vs Node.js Express/Locomotive/Sails) и отдельно — работа с веб-сокетами. Node всегда оказывался существенно быстрее — от 1.5x-3x до 10x. Задачи разные, но специфичные, и, как я подозреваю, для других задач — могли быть другие результаты. Да, PHP запускался на Apache 2.2 как FastCGI (FPM).

                                                                                                  Далее — PHP сильно спасает PHP-FPM и opcode cache. Но при большом количестве обрабатываемых данных скорость выполнения V8 отрывается все дальше. При большом количестве работы с сетью (отдача и получение данных) — Node отрывается все дальше. По количеству одновременных живых подключений — Node оказывается вне конкуренции. Лучше всего видно с ростом нагрузки и одновременной обработки данных. Однако, не сказать, что PHP совсем уж плох в плане производительности (Ruby/Rails в разы «хуже» :). Забавно, что производительность Node так же точно падает с количеством используемых на нем фреймворков и тулзов. Но эта же проблема есть и у PHP, и по общим ощущениям — каждый «function call» тормозит PHP сильнее, чем V8. Куда менее выражен этот эффект у .NET/Java.

                                                                                                  В целом — возможно, слишком громкое заявление о том, что PHP неповоротлив — вполне возможно, что решаемые в моих проектах задачи имели такую специфику, но я же из своего опыта и говорю. .NET — опять же по опыту, очень быстр, и несмотря на отрыв в несколько раз — Node наступает ему на пятки. Не разбираюсь в таких «низкоуровностях», но оно и понятно — у V8 какая-то гениальная виртуальная машина с JIT-компилятором. Не без ложки дегтя — жрет много ресурсов.

                                                                                                  В довесок. Интересно, что для ряда общих задач аналогичная Node (и даже чуть выше) производительность была у Python на PyPy. А вот Ruby (MRI) был медленнее в десять и более раз. С рельсами — в 20 :)
                                                                                                    0
                                                                                                    Возможно мы не замечаем неторопливости PHP, потому что используем его в основном для двух задач: подготовить запрос к БД или SOAP сервису и отформатировать вывод результата запроса. Приложение одностраничное — отсылается минимально необходимый html в ответ на ajax-запросы, обычно это содержимое одного div'а, который тупо вставляется в DOM браузера. Ну и используем свой микрофреймворк, заточенный под эти задачи. Да, тоже можно сказать, что интранет-приложение — неаутенфицированные пользователи видят только форму входа. В общем всё у нас упирается в БД или SOAP (за которым специализрованная БД по сути).
                                                                                        0
                                                                                        Node.js поддерживает fiber'ы. Так что нет, никаких 15мс простоя не будет в правильно написанном приложении.
                                                                                          0
                                                                                          Cluster вполне себе неплохо работает. Но он подходит не для всех сценариев масштабирования и распределения нагрузки.
                                                                                          Мы можем создать, скажем, 16 одинаковых процессов (по количеству ядер) с помощью Cluster, и каждый из них будет блокироваться любой CPU-intensive-операцией, но остальные будут работать. А можем использовать Fibers (виртуальные трэды) или Threads A Go-Go (реальные трэды, но со своими особенностями, конечно же).

                                                                                          Каждый из подходов имеет право на жизнь и зависит от проекта, задачи и предпочтений архитектора. То, что не нужно блокировать главный event-loop — это очевидно.
                                                                                  +6
                                                                                  Автор сравнивает производительность node.js с другими языками, так, как будто там нет асинхронных библиотек.

                                                                                  Если у вас куча подключений и куча событий вам не нужна node.js — в Руби для этого есть EventMachine, в Пайтоне — Twisted. Та же архитектура и та же устойчивость.

                                                                                  Но, например, в Руби 1.9 есть хорошая технология для решения проблемы кучи коллбэков — файберы, которые позволяют писать асинхронный код в синхронном стиле (но имеет ряд плюсов перед IcedCoffeeScript).
                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                      0
                                                                                      Для таких случаев в EM есть EM.defer
                                                                                      см.
                                                                                      eventmachine.rubyforge.org/EventMachine.html#defer-class_method
                                                                                      github.com/eventmachine/eventmachine/wiki/EM::Deferrable-and-EM.defer
                                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                                          +1
                                                                                          EM сама по себе использует тот же паттерн, что и nodejs — en.wikipedia.org/wiki/Reactor_pattern
                                                                                          Т.е. асинхронная модель и один тред. НО в EM существует workaround для библиотек, которые не умеют работать с IO в асинхронном режиме (mysql ЕМНИП) — EM.defer — это пул из тредов, которые могут блокироваться, что в главном треде позволить нельзя.

                                                                                          GIL во время блокируемых IO операций освобождается, и в это время другие потоки работают.
                                                                                          Т.е. если у Вас блокируемые операции IO — выносите их в EM.defer.
                                                                                        +2
                                                                                        Зато сейчас у Python из коробки имеется отлаженный механизм корутин. А с Python 3.3 и yield from корутинами стало возможно пользоваться без монстрообразных консктрукций а-ля лишних for и try..except
                                                                                      +11
                                                                                      А расскажите, пожалуйса, те, кто активно использует node.js в БОЛЬШИХ проектах: как вы живете без обработчиков исключений? Желательно с примером. Это же ад — в каждую-каждую функцию везде передавать обработчик ошибок и тащить его через весь стек вызовов (например, A вызывает B, B вызывает C, C вызывает D — и вот, чтобы проверить статус ошибки из D в A, придется через B и C протаскивать дибо колбэк, либо хотя бы код ошибки). Хотя обработка исключений и поддерживается в минимальном виде в js (если это можно назвать поддержкой), совершенно же ясно, что она не годится для асинхронного кода.
                                                                                        0
                                                                                        Да, именно так это и называется — callback hell. Ошибки, как правило, эскалируются вверх до определенного уровня, и там уже обрабатываются.
                                                                                        Обработкой исключений (try..catch, throw), используется редко, при этом только для синхронных операций, чтобы потом поймать и в асинхронном стиле передать ошибку.
                                                                                        От callback hell в скором времени можно будет избавиться, используя generators описанные в черновике ECMAScript 6. Они уже есть в unstable node.js v0.11.
                                                                                          +3
                                                                                            –2
                                                                                            Это не то же. Совсем другая концепция, нежели исключения, плюс — тяжелая штука!
                                                                                            +4
                                                                                            В мире Node.js (начиная от самогó API Node.js) принято делать так, чтобы все коллбэки (функции обратного вызова) имели минимум два аргумента, первый из которых — состояние ошибки (то есть имеет значение, равное либо null, либо экземпляру объекта Error). Если этот аргумент не null, то обработка остальных аргументов прекращается (тем более что в реальном обратном вызове они в случае ошибки чаще всего и не заполняются).

                                                                                            Вместо «throw new Error(…)» в асинхронном коде пишут «callback(new Error(…))», что не сложнее.

                                                                                            Если функция обратного вызова не занимается обработкой ошибок на своём уровне, то передаёт их обратному вызову более высокого уровня.

                                                                                            Вот пример такой передачи для ошибки ввода-вывода при чтении файла, в котором настройки лежат:

                                                                                            var fs = require('fs');
                                                                                            
                                                                                            var readSettings = function( filename, callback ){
                                                                                               fs.readFile( filename, { encoding: 'utf8' }, function( err, data ){
                                                                                                  if( err ) {
                                                                                                     callback(err); // ← вот так делается передача ошибки!
                                                                                                     return;
                                                                                                  }
                                                                                            
                                                                                                  // далее следует обработка прочитанных из файла сведений…
                                                                                            
                                                                                                  callback( null, обработанныеДанные );
                                                                                               });
                                                                                            };
                                                                                            

                                                                                            Как видите, вглубь не передаётся внешний коллбэк. Однако код ошибки именно протаскивается наружу. Это делается одной строчкою, никакого особенного ада нет в этом.
                                                                                              +3
                                                                                              Сразу скажу ещё, что пишу «это делается одной строчкою» оттого, что на практике почти никто не употребляет, на сáмом-то деле, целых четыре строки:

                                                                                              if( err ) {
                                                                                                 callback(err);
                                                                                                 return;
                                                                                              }
                                                                                              

                                                                                              (такая запись у меня в вышеизложенном комментарии дана просто для наглядности).

                                                                                              А пишут «if( err ) return callback(err)» в одну строчку, как правило — да и всё.
                                                                                                +3
                                                                                                Как видите, вглубь не передаётся внешний коллбэк
                                                                                                Это у вас пример простой просто, все вызовы на одном экране и в одном и том же замыкании. На практике же вызовы меняют контекст замыкания частенько. Да и явно тащить везде первый аргумент, плюс лишний иф — это я и называю несовершенностью языка в части обработки исключений (непродуманность).
                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                    0
                                                                                                    Сложных примеров быть не должно. Если вложенность колбэков слишком большая, из разносят в разные части кода, делают декомпозицию через async и подобные библиотеки, делают фабрики звеньев цепи, и используют прочие паттерны. Некоторые вообще рекомендуют избегать создания анонимных функций, особенно в циклах, включая forEach. Хороший код не содержит глубоких «ёлочек». Пример правильной организации логики обработки — цепи middleware в express (точно так же можно организовать любые цепи, например последовательные запросы к БД). Если в nodejs появляется «елочка» — это уже повод задуматься, что что-то идёт не так. Как выглядит аккуратный код с декомпозицией, хорошо показывает пример (stackowerflow):

                                                                                                    function loadUser(req, res, next) {
                                                                                                      if (req.params.userId) {
                                                                                                        Users.findOne({ id: req.params.userId }, function(err, user) {
                                                                                                          if (err) {
                                                                                                            return next(new Error("Couldn't find user: " + err));
                                                                                                          }
                                                                                                          req.user = user;
                                                                                                          next();
                                                                                                        });
                                                                                                      } else {
                                                                                                        next();
                                                                                                      }
                                                                                                    }
                                                                                                    
                                                                                                    // ...
                                                                                                    
                                                                                                    app.get('/user/:userId', loadUser, function(req, res) {
                                                                                                      // do something with req.user
                                                                                                    });
                                                                                                    
                                                                                                    app.get('/users/:userId?', loadUser, function(req, res) {
                                                                                                      // if req.user was set, it's because userId was specified (and we found the user).
                                                                                                    });
                                                                                                    
                                                                                                    // Pretend there's a "loadItem()" which operates similarly, but with itemId.
                                                                                                    app.get('/item/:itemId/addTo/:userId', loadItem, loadUser, function(req, res) {
                                                                                                      req.user.items.append(req.item.name);
                                                                                                    });
                                                                                                    
                                                                                                    function requireAdmin(req, res, next) {
                                                                                                      if (!req.user || !req.user.admin) {
                                                                                                        return next(new Error("Permission denied."));
                                                                                                      }
                                                                                                    
                                                                                                      next();
                                                                                                    }
                                                                                                    
                                                                                                    app.get('/top/secret', loadUser, requireAdmin, function(req, res) {
                                                                                                      res.send('blahblahblah');
                                                                                                    });
                                                                                                    
                                                                                                      +2
                                                                                                      Согласен, что елочек быть не должно. Step, Fibers, async, Q и другие — решают задачи callback hell-а, еще его очень по-своему решает streamline.js (preprocessing), но все должно здорово поменяться с появлением поддержки генераторов и yield в стабильной ветке Node. Все-таки сейчас эта проблема организации асинхронного кода, согласитесь, занимает энное количество CPU-циклов головы любого разработчика на Node.js.

                                                                                                      "*" и «yield», правда, не самые удачные обозначения — на мой взгляд, дотнетовские async/await (особенно await) куда удачнее в плане терминологии, но это уже дело вкуса.
                                                                                                      0
                                                                                                      Не поспоришь, не без недостатков все это дело, но пока удается выкручиваться с вещами, вроде Q
                                                                                                    0
                                                                                                    Мы, например, полностью надеемся на промис фейлы и домейны — пока что не подводили.
                                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                        0
                                                                                                        Примерно так:

                                                                                                        var get = $jin.async2sync( $node.request.get )
                                                                                                        var save = $jin.async2sync( $node.fs.writeFile )

                                                                                                        var download = $jin.sync2async( function( from, to, def ){
                                                                                                        var isDefault = false
                                                                                                        try {
                                                                                                        var content =get( from )
                                                                                                        } catch( error ){
                                                                                                        content = def
                                                                                                        var isDefault = true
                                                                                                        }
                                                                                                        save( to, content )
                                                                                                        return isDefault
                                                                                                        })

                                                                                                        download( 'http://ya.ru', 'ya.ru.html', '', function( error, isDefault ){
                                                                                                        console.log( 'isDefault: ' + isDefault )
                                                                                                        })

                                                                                                        То есть благодаря node-fibers любую асинхронную функцию можно превратить в синхронную и наоборот с любой степенью вложенности. Более того, благодаря harmony proxy есть возможность автоматического параллелизма. Пример: github.com/nin-jin/node-jin#sod
                                                                                                        +5
                                                                                                        Да, именно так это и называется — callback hell. Ошибки, как правило, эскалируются вверх до определенного уровня, и там уже обрабатыва

                                                                                                        Нет, это не callback hell. Потому что callback hell — это написание кода лесенкой, он легко решается, лесенка спрямляется (а coffeescript еще и сокращает письмо до приемлемого уровня). Проблема обработки ошибок — совершенно отдельная. Фактически, нас отбрасывает назад к временам Си, но в СИ хоть есть longjmp (активно используемый в больших проектах, между прочим). ИМХО до тех пор, пока в node.js не появится механизма, позволяющего обрабатывать исключения в той же самой идеологии, что и в остальных языках, заглавие топика останется справедливым (может, он уже появился? о том и мой вопрос был).
                                                                                                          –1
                                                                                                          Callback hell это не только лесенка в коде, но и то что ошибки приходится эскалировать. Coffeescript помогает сократить письмо до приемлемого уровня, но всё равно каждый раз приходится писать: return callback(err) if err?.
                                                                                                          Наверное вы правы, что это совершенно другая проблема. Вот только я не до конца понимаю какая. Можете объяснить чем принципиально отличается идеология обработки ошибок в ноде, с идеологий обработки ошибок в пхп?
                                                                                                            0
                                                                                                            На обычном JavaScript также можно записать «if( err ) return callback(err)», так что в этом коде переход на CoffeeScript не приносит существенной экономии.
                                                                                                              –3
                                                                                                              А что тут объяснять?
                                                                                                              man try-catch :)
                                                                                                                +3
                                                                                                                Допустим имеем 10 уровней вложенности вызовов (что нормально для PHP и, наверное, мало для Node.js ). На 10-м уровне происходит вызов ФС, который может закончитья с ошибкой. Обработка этой ошибки требуется только на самом верхнем уровне — записать детали ошибки в лог и выдать 5xx пользователю. На PHP на 8 уровнях из 10 об этой ошибке вообще не надо думать, только на нулевом и последнем. Node.js же потребует на этих уровнях написать минимум по строчке if( err ) return callback(err);, если такая запись допустима стандартами кодирования, а не требуется её разворачивать в
                                                                                                                if( err !== null ) {
                                                                                                                  callback(err);
                                                                                                                  return;
                                                                                                                }
                                                                                                                

                                                                                                                А если на определенном внутреннем уровне нам необходимо обработать ошибки строго определенного типа, то на PHP нам нужно написать нечто вроде:
                                                                                                                try {
                                                                                                                  File::remove($filename);
                                                                                                                catch (FileNotExistsException $e) {
                                                                                                                  Log::write('Config file not exists. Default values using.');
                                                                                                                }
                                                                                                                
                                                                                                                , а на js, как я понимаю, придется писать что-то вроде
                                                                                                                file.remove(filename, function (err) {
                                                                                                                if (err) {
                                                                                                                  if (err instanceof FileNotExistsError) {
                                                                                                                    log.write('Config file not exists. Default values using.');
                                                                                                                  } else {
                                                                                                                    callback(err);
                                                                                                                    return;
                                                                                                                  }
                                                                                                                } 
                                                                                                                
                                                                                                                ,
                                                                                                                что субъективно более громоздко и непонятно.
                                                                                                                0
                                                                                                                Проблемой активно занимаются. Смотрите про Node.js Domains (ссылка на статью на Хабре). В ранних версиях действительно не было вообще ничего вменяемого, и это было тем еще гвоздем в заднице.
                                                                                                                +11
                                                                                                                возможно на порядок больше, чем вы могли бы получить, используя PHP, .NET или RoR
                                                                                                                Эм. В дотнете уже года полтора как есть поддержка удобной (неудобная в виде Begin/EndSmth с колбеками и IAsyncResult была с бородатых времён) асинхронщины в виде async/await, которая позволяет писать код в императивном стиле абсолютно точно не блокирует вызывающий поток, и на тысячи запросов в секунду будет хватать пула из пары десятков потоков. Стек ASP.NET 4.5 и ASP.NET MVC 4.0 этот подход дают с успехом использовать. Единственная проблема — ещё не все ORM и коннекторы к БД это поддерживают.
                                                                                                                  –3
                                                                                                                  async/await создает треды, что не является аналогом асинхронности в ноде.
                                                                                                                    +5
                                                                                                                    Не создаёт. Почитайте, как оно внутри работает. Вкратце: по завершению асинхронной по своей природе операции (файловый/дисковыйввод-вывод) обработчик её результата вызывается в контексте синхронизации, из которого эта операция была инициирована. В случае веб-приложения этому контексту соответствует «любой поток из стандартного пула потоков», но можно реализовать свой контекст и сделать обработку принудительно однопоточной, однако, такой вариант видится неэффективным на многоядерных процессорах. С самой же асинхронной операцией (которая на самом деле Begin/End с IAsyncResult, обёрнутая в таск) никаких потоков не сопоставлено, в Windows её окончания ожидают через I/O Completion Port, в никсах Mono держит отдельный поток, который ждёт событий через epoll/kqueue и передаёт эти события куда следует.
                                                                                                                    +4
                                                                                                                    Какой там async/await, тут даже обычный yield мог бы сильно улучшить ситуацию. К слову, механизм генераторов давно есть вообще во всех мало-мальски известных языках для веб-разработки… кроме Javascript. Кроме, блин, именно того языка, где они необходимы как воздух из-за асинхронной природы API.
                                                                                                                    Даже не представляю, чем можно объяснить такое безобразие.
                                                                                                                      0
                                                                                                                      В Javascript 1.7 yield есть (ИЧСХ поддерживается мозилловскими движком), проблема в V8, не имеющем поддержки Javascript 1.7.
                                                                                                                        0
                                                                                                                        V8 недавних версий получил поддержку «yield» и генераторов.

                                                                                                                        Сборка Node.js тестовой версии 0.11.2 (и более новых) имеет эту поддержку.
                                                                                                                          0
                                                                                                                          Остаётся тогда только один существенный недостаток — невозможность нормальной обработки исключений, вызванных асинхронными операциями. Хотя, можно их оборачивать, но это уже не так красиво выглядит.
                                                                                                                            –1
                                                                                                                            Не вижу проблем с отладкой.
                                                                                                                            // present
                                                                                                                            app.get('/users/', function (req, res, next) {
                                                                                                                                db.select('users')
                                                                                                                                .then(function (users) {
                                                                                                                                    return users.toJSON();
                                                                                                                                })
                                                                                                                                .then(res.json, next);
                                                                                                                            });
                                                                                                                            

                                                                                                                            // future
                                                                                                                            app.get('/users/', function *(req, res, next) {
                                                                                                                                try {
                                                                                                                                    var users = yield db.select('users');
                                                                                                                                    res.json(yield users.toJSON());
                                                                                                                                } catch (e) {
                                                                                                                                    next(e);
                                                                                                                                }
                                                                                                                            });
                                                                                                                            
                                                                                                                              +1
                                                                                                                              Код не эквивалентен. Если users.toJSON аснхронная, то и в первом куске надо работать с ним асинхронно. Поскольку then ждет ответа у же к return, то как с его вернуть — не понятно.
                                                                                                                                –1
                                                                                                                                Код абсолютно идентичен и интерфейс объекта работы с БД одинаковый (возвращает promise) как в первом так и во втором примере.
                                                                                                                    –3
                                                                                                                    А если отрезать себе ноги, может стать больно.
                                                                                                                    Спасибо, капитан очевидность.
                                                                                                                      +5
                                                                                                                      Кстати, а как вам sails.js. Очень удивился, что за него никто не вспомнил.
                                                                                                                        0
                                                                                                                        Тож удивлен. Но думаю тут как со всеми хорошими модулями в ноде — они теряются в массе
                                                                                                                          0
                                                                                                                          Да, sails выглядит весьма прилично, спасибо за наводку. Поиграюсь на досуге.
                                                                                                                          +4
                                                                                                                          И в этом посте нет promise-срача? Хабр уже не торт.
                                                                                                                            +1
                                                                                                                            Тьюринг-полнота программиста — программист должен написать язык программирования, который должен быть тьюринг-полным.
                                                                                                                              0
                                                                                                                              Предпоследний азбац про Bitbucket, Jade, ASPA вообще непонятно каким образом относится к преимуществам node.js vs php?
                                                                                                                              Кто-нибудь объяснит?
                                                                                                                                0
                                                                                                                                Пожалуй они в новом проекте просто нашли применение новым технологиям и практикам.
                                                                                                                                Это просто преимущество современного vs legacy кода.
                                                                                                                                +7
                                                                                                                                выжимка из комментариев: «Тебе все равно никто не поверит»
                                                                                                                                  0
                                                                                                                                  Хотел не согласится с некоторыми утверждениями по содержимому статьи. Но прочитав оригинал, и понял, что проблема в переводе.
                                                                                                                                  Смотрим на название «Node.js не подходит для типовых веб-проектов». Далее в тексте видим «Устаревшие данные», «Callback hell». Пусть оригинальный автор мена простит, но для типовых проэктов подходят CMS, * Platform, и другие законченные решения. Nodejs это платформа, а не законченное решение. Так что либо слово «типовых» ну никак не подходит. Смотрим в оригинал и видим generic web projects. В данном контексте, верный перевод есть Node.js не подходит для обычных веб-проектов.
                                                                                                                                  «Литературный перевод» второго предложения опять несколько изменил смысл. В оригинале предложение отвечает на вопрос «для чего предназначен nodejs?», в переводе вопрос уже другой.

                                                                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                                      –1
                                                                                                                                      Вот при всем уважении не понимаю я мазохизма программировать в JavaScript и прочих скриптовых языках большие проекты. Программировать надо на строготипизированном со статической типизацией компилиуемом языке (C#|Java). Там хотя-бы глупые ошибки сразу вылазят в процессе компиляции да и рефакторинг нормально работает…
                                                                                                                                        +2
                                                                                                                                        А можно просто глупых ошибок не делать. Или делать проверки на этапе выполнения, тем более что чаще всего в контексте веб-разработки код не отчуждается и/или доступен пользователю и может быть поправлен на лету хоть прямо на боевом сервере за секунды без длительной компиляции и сборки.

                                                                                                                                        В общем, имхо, куда важнее правильность значений результатов, а не их типов.
                                                                                                                                        0
                                                                                                                                        не понимаю почему nodejs считается скоростным решением. любое приложение .net и java на асинхронно-событийной модели обгонит его в разы.
                                                                                                                                        nodejs — это 1 поток и 500 метров оперативки. Как java разработчик я не могу понять как написать на языке без строгой статической типизации приложение больше 1000-и строк. люди жуют кактус (можете почитать что пишет команда trello) и внушают себе что получают удовольствие от этого (можете опять почитать что пишет команда trello).
                                                                                                                                        Ну и ладно.
                                                                                                                                          +1
                                                                                                                                          Обгонит, безусловно. Но не в разы. В этом вся суть, что простой динамический язык с утиной типизацией может «летать» на скорости, близкой к компилируемым языкам со статической типизацией.

                                                                                                                                          Как java разработчик я не могу понять как написать на языке без строгой статической типизации приложение больше 1000-и строк.
                                                                                                                                          Даже будучи 7 лет разработчиком и архитектором C#/.NET (до полного перехода на альтернативные платформы) понимал как — все дело в организации кода, а не в его системе типизации.
                                                                                                                                          0
                                                                                                                                          Половина комментариев из серии «10 лет на php/java/etc, не верю что node быстрее».
                                                                                                                                          Главная мысль, которую пытается донести автор — node созрел для продакшена.

                                                                                                                                          Про скорость работы сервера — ну, это ж как напишешь, верно?

                                                                                                                                          Ещё один плюс, про который забывают — это то что у тебя весь проект на одном языке. И фронтенд и бекенд, т.е. скорость разработки в команде потенциально должна быть выше, а так же выше уровень взаимозаменяемости членов команды.
                                                                                                                                            0
                                                                                                                                            Не верю, что разработка (читай — реакция на изменившиеся бизнес-требования) на node.js быстрее чем на PHP :)

                                                                                                                                            Один язык, да, плюс. Но сильно ли значимый, если и так взаимозаменяемость высокая в плане технологического стэка и куда больше зависит от того, кто какой модуль писал?
                                                                                                                                              0
                                                                                                                                              Она и не быстрей =)
                                                                                                                                              Тут всё индивидуально. Кто-то и на джаве быстрее напишет, с учётом всех редеплоев — просто потому что мозги так у человека работают.
                                                                                                                                              Автор вообще знатно вбрасывает удобрений в вентилятор: одно то что «нод быстрее работает» — тема для холиваров на 10 лет вперёд.

                                                                                                                                              Я бы сказал так: У Node JS есть предпосылки к тому, что бы написать на нём быстрый код. И у Node JS, опять же, есть предпосылки для более высокой скорости разработки за счёт лучшей синергии между разработчиками.

                                                                                                                                              Проблемы у Node ровно две, и обе они такие же как у php:
                                                                                                                                              1. Люди не серьёзно относятся к языку, считая его уг по умолчанию;
                                                                                                                                              2. Разработчики, зачастую, плохо его знают и пишут соответствующий код;

                                                                                                                                              Нет, правда, мне вот стыдно говорить людям, что я «Программист JavaScript» — по лицам видно, как все представляют себе «снежинки на сайте»

                                                                                                                                            0
                                                                                                                                            Node очень сложен для новичков. Я, например, являюсь таковым. Если RoR показался мне очень дружелюбным и плавно двигаясь через терни я достигаю результата, то открыв Node я оказался за штурвалом межгалактического шаттла. Я думаю годик-два на рельсах, а там уже можно и на ноду еще разок посмотреть. Я прав?
                                                                                                                                              0
                                                                                                                                              Просто неверно сравнивать Node и Rails. Можно сравнивать Node и Ruby, как язык и среду исполнения (MRI, например). Рельсы создают такое ощущение — потому что это готовый (и отличный при этом) фреймворк для решения именно вашей задачи. С Node дела обстоят по-другому. Но если хотите jump-start-нуть, попробуйте сразу решать задачу, скажем, на Sails.js, Locomotive.js или подобном.
                                                                                                                                              +1
                                                                                                                                              Абсолютно с вами согласен. Имхо дело в реализации, а закопать можно даже проект с идеальной архитектурой. Несколько лет назад я бы сам не поверил, что можно написать например браузерную игру с сервером на nodeJS.

                                                                                                                                              Пруф pi-online.ru
                                                                                                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                                                  0
                                                                                                                                                  Это всего лишь стилистика. Суть в бек-энде )
                                                                                                                                                0
                                                                                                                                                Пэхапэшники с CMS головного мозга против суровых яваскрипторов и дотнетчиков. Исторический мини-батл, спасибо, было интересно.
                                                                                                                                                  0
                                                                                                                                                  Кстати авто сайт упал, не в курсе, переписывают заново на другом яп или оптимизируют?
                                                                                                                                                    –1
                                                                                                                                                    Большие корпорации используют Python и C++ (Яндекс, Google) и иногда даже PHP (Facebook).
                                                                                                                                                      0
                                                                                                                                                      А что мешало до этого с php использовать Битбакет, какойнить фреймворк с MVC паттерном, к примеру тот же Yii???
                                                                                                                                                      Делали очень много серьезных вещей на NodeJS: различные статистики, ротаторы рекламы, админ интерфейс на Angular + nodeJS.
                                                                                                                                                      На мой взгляд для таких проектов как ваш очень хорошо подходит PHP

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

                                                                                                                                                      Самое читаемое