Ответы пользователя по тегу Node.js
  • Node.js сервер запущен – почему страница в браузере не открывается?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Возможно, после добавления правила в iptables Вы не сохранили таблицу через service ip6tables save и перегрузили тазик. Чтобы проверить хоть в нем ли проблема, отключите его на время через service ip6tables stop проверьте в браузере и потом включите через service ip6tables start и вовсе убрать фаервол из актозагрузки можно через chkconfig ip6tables off, а вернуть через chkconfig ip6tables on. Попробуйте так же правило такое:
    iptables -A INPUT -p tcp -m tcp --dport 8888 -j ACCEPT
    Но еще нужно проверить, на тот ли IP (hostname) делает bind нодовский сервер, через функцию server.listen(port, [ip]). Если поставить IP "0.0.0.0", то он сядет на все интерфейсы. Если не поможет все это, то проверять нужно фаервол у датацентра/хостинга, возможно там есть панель управления, в которой можно пробросить порты во внешний мир.
    Ответ написан
    Комментировать
  • Какую IDE/Editor вы используете для Node/JS?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Посмотрите вот этот зоопарк https://github.com/shuvalov-anton/code-screenshots
    Лично мой выбор Far Manager, Midnight Commander, Droid Edit, ConEmu
    Ответ написан
    Комментировать
  • Как задать всем гетам один параметр?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Если Вы собрались ловить любой get запрос, то Вам вообще не нужен express, хватит http.createServer(function (req, res) { /* любой запрос попадет сюда */ }).listen(80); А экспресом app.get('*', function (req, res) { /* любой запрос попадет сюда */ });
    Ответ написан
    Комментировать
  • Можно ли запустить программу на Node.js без окна терминала?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Как и любую консольную программу, тут есть варианты: superuser.com/questions/62525/run-a-batch-file-in-...
    Или есть такая программа RunAsService: runasservice.sourceforge.net
    Ответ написан
    Комментировать
  • Есть ли Сообщество людей, знающих русский, из области nodejs?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    gitter.im/dev-ua/node
    Ответ написан
    Комментировать
  • Как наиболее удобным способом получить настоящее имя файла?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    console.dir(process.argv);
    console.log(process.argv[1]);
    console.log(__filename);
    Ответ написан
  • Как установить phonegap из npm?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Там же кучу всего из исходников должно компилироваться, для этого нужен целый воз всего. Python стоит? Node-gyp стоит? MS Visual Studio? Прописаны ли пути ко всему этому в PATH? Еще советую проверить права к папкам и попробовать запустить консоль из-под админа и оттуда устанавливать. Тут похожая ситуация рассматривается: https://github.com/TooTallNate/node-gyp/issues/277 Ну и высылаю, как при успешном билде должен выглядеть вывод в консоль, из этого можно почерпнуть вот что:
    1. У вас не может сбилдиться первая из компилируемых зависимостей, модуль ws, а именно bufferutil.cc, возможно, npm не там его ищет или не имеет достаточно прав для доступа к нему или к компилятору
    2. Могут быть дополнительные проблемы с geoip-lite, т.к. он при установке качает много из интернета и конвертирует базы, попробуйте ставить его отдельно npm install geoip-lite и посмотрите какой вывод.
    Ответ написан
  • Как понять принцип работы с файловой системой?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Думаю, что ни какие классы тут не нужны, просто нужно сделать все в стиле API, разбить его на 2 слоя:
    • Слой доступа к данным (работает с fs и является оберткой, утилитами, позволяющими упростить работу с файлами для следующего более абстрактного слоя), кладем в файл storage.js, структура такая:
      var storage = {};
      module.exports = storage;
      storage.read = function(name, callback) {
        ...
        callback(data); // отдаст data или null
      };
      storage.write = function(name, data, callback) {
        ...
        callback(); // без папаметров
      };
      storage.exists = function(name, callback) {
        ...
        callback(exists); // отдаст true/false
      };

    • Слой обработки данных (парсер и т.д.), кладем в файл processing.js - он использует storage.js как зависимость через require:
      var storage = require('storage');
      var processing = {};
      module.exports = processing;
      processing.parse = function(data) {
        ...
        // тут можем парсить и вызывать storage API
        return parsedStructures;
      };


    А теперь в коде верхнего уровня используем обе библиотеки:
    var storage = require('storage');
    var processing = require('processing');
    // далее можем использовать оба API storage и processing
    storage.exists(name, function(exists) {
      if (exists) {
        // если файл есть, то читаем
        storage.read(name, function(data) {
          // и теперь его парсим
          var matrix = processing.parse(data);
          // делаем что нужно
        });
      } else {
        // если нету, то создаем дэфолтную структуру
        var matrix = { default: "structure" };
        storage.write(name, matrix, function() {
          // и пишем ее на диск
        });
      }
    });
    Ответ написан
    Комментировать
  • Как написать обработчик в NodeJS, отправляющий запрос перед завершением процесса?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Смотря как завершается процесс, если по сигналам, то опробуйте:
    //do something when app is closing
    process.on('SIGINT', drainArray); // выход по Ctrl-C из консоли
    process.on('SIGTERM', drainArray); // завершение через kill
    process.on('exit', drainArray); // выход по собственному желанию
    process.on('uncaughtException', drainArray); // если свалился

    Но сделайте глобальный флаг и проверяйте его в drainArray, чтобы не запустить 2 раза:
    var drainArray = function() {
      if (!process.flagExit) {
        process.flagExit = true;
        // отправка данных
      }
    };
    Ответ написан
  • За сколько секунд стартует ваше приложение node.js в production-е?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Начинает отчечать по http через ~2сек после старта
    Ответ написан
    Комментировать
  • Как установить пакет db-mysql с npm?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Это какой-то не поддерживаемый пакет, последняя версия 3 года назад, похоже, что он уже не совместим с актуальной версией npm, активности в репозитории нет. Ставьте лучше вот этот https://www.npmjs.org/package/mysql
    npm install mysql
    И посоветую свои дополнения к нему: https://www.npmjs.org/package/mysql-utilities
    npm install mysql-utilities
    Ответ написан
    1 комментарий
  • GET Request Nodejs без Express?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    var http = require('http');
    http.createServer(function (req, res) {
      if (req.method === 'GET' && req.url === '/read') {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Hello World');
      } else res.end('You should open /read');
    }).listen(81);

    Но так писать это же сколько if-ов будет. Если express не нравится, то попробуйте impress. Там такой же обработчик можно сделать проще, создаете папку /read и кладете в нее html.template с нужным HTML и ни какого кода, а API метод: /api/method.json вызываемый через POST: делаете файл /api/method.json/post.js (или любой другой HTTP метод delete.js, get.js...) и в нем:
    module.exports = function(client, callback) {
        dbImpress.users.find({ group: client.fields.group }).toArray(function(err, nodes) {
            callback(nodes);
        });
    }

    Результат:
    [
        { "login": "Vasia Pupkin", "password": "whoami", "group": "users" },
        { "login": "Marcus Aurelius", "password": "tomyself", "group": "users" }
    ]
    Ответ написан
    Комментировать
  • Как реализовать Подгрузку контента в node.js?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Берите SSE (Server-Sent Events) или WebSocketы в реализации socket.io или любой другой (это просто разные обертки, а в варианта вот два), если не считать устаревшего long pooling ака commet, но кому он нужен на ноде то. В примере чата Вы найдете все, что нужно socket.io/get-started/chat или поиском по NPM https://www.npmjs.org/browse/keyword/sse и так еще https://www.npmjs.org/browse/keyword/websocket найти там можно многое, но лучше https://www.npmjs.org/package/websocket и https://www.npmjs.org/package/sse там еще проще все. Если захочется все вместе на одном порту и websocket и SSE и REST API и RPC API и веб-страницы и статику, то смотрите мой https://github.com/tshemsedinov/impress и статьи по нему на хабре найти можно, слайды тут у меня на www.slideshare.net/tshemsedinov и примеры внутри идут.
    Ответ написан
    Комментировать
  • Как при распараллеливании nodejs приложения по разным серверам иметь единый массив пользовательских сессий?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Самое лучшее, это держать сессии и общее состояние (например, модель игрового мира или машину состояний, используемую для управления объектом промышленной автоматизации и т.д.) в оперативной памяти. Сессии только в одном процессе, а общее состояние в каждом процессе. Чтобы клиент подключался всегда к тому процессу, в котором лежит его сессия, то соединение должно быть подписано специальной cookie с номером процесса, кука эта может устанавливаться при аутентификации и после этого, сетевой маршрутизатор или реверс-прокси будет передавать все запросы, помеченные этой кукой, именно в нужный процесс. Но процессы дохнут периодически, поэтому сессии нужно сохранять в БД, но лучше это делать в ленивом (lazy) режиме, т.е. не во время HTTP запроса от клиента, а поставить периодическое событие и сбрасывать из памяти в БД, и иметь механизм восстановления из БД. Если процесс пользователя погиб, то при первом следующем запросе состояние восстановится и дальше будет опять браться из памяти. Можно сделать упреждающее чтение, если процесс погибает, то в БД хранить для каждого процесса массив пользователей, чье состояние он обрабатывал и сразу после повторного запуска, процесс восстановит из БД все сессии и будет ждать "своих" пользователей. Что касается общего для многих пользователей состояния, то его можно синхронизировать между процессами при помощи нехитрого API, пересылающего лог изменений состояния из того процесса, в котором они произошли во все другие при помощи IPC, HTTP или ZeroMQ. Пример такого API вот тут: https://github.com/tshemsedinov/impress/blob/maste... Вкратце, оно имеет функции inc(path, value, delay); dec(path, value, delay); set(path, value, delay); get(path); delete(path, delay); и т.д. тут path - это путь к данным в объекте состояния, например inc('myCar.speed', 15, "2s") - увеличить скорость машины в модели на 15 с гарантированной синхронизацией между процессами в течении 2 секунд (это для того, чтобы сократить кол-во пересылок изменений, они склеятся в течении 2 секунд). Все inc/dec изменения аддитивны в любом порядке, поэтому их можно пересылать как угодно, а в другом процессе можно подписаться на изменение subscribe('myCar.speed', function(path, value, remote) { ... }); где path - 'myCar.speed', value - новое значение, remote - true если изменение из другого процесса. Думаю, что Вы найдете и более подходящие реализации, но пример должен быть понятен. Можно конечно держать и сессии и общее состояние в БД, например в MongoDB, но это приводит к тому, что во время HTTP запросов случается I/O, и запрос ждет, а согласитесь, что ни какого I/O это быстрее, чем асинхронное I/O, брать из памяти - всегда лучше, а синхронизировать в свободное время (пусть с ограниченной точностью, с отставанием), а если личные сессии, то ни какого отставания вообще нет.
    Ответ написан
    Комментировать
  • В чем проблема с Node.js ?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    После запуска node и получения приглашения можете писать JavaScript так: require('./helloworld'); А из командной строки запускается через node helloworld, писать с расширениями node.exe helloworld.js, как советуют выше, не обязательно. Командную строку запускать в винде нажатием Win+R и вводим cmd и жмем enter.
    Ответ написан
  • Как через Nginx проходят такие запросы?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Ничего странного нет, удаленный клиент подключился к твоему IP и прислал в сокет строку GET 37.28.156.211/sprawdza.php Тут он мог прислать любой URL. А отдала страницу нода, потому, что она, скорее всего, тоже не проверяет host в запросах. Лучше всего фильтровать по host в nginx. Проверь, чтобы нода делала server.listen(8080, '127.0.0.1'); а не просто server.listen(8080); Эксплуатировать такую проблему ни как нельзя, кроме как DOSить, это не сильно страшно, но фильтровать по хостам нужно.
    Ответ написан
  • Node.js + socket.io и mysql как организовать соединение?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Нужно открывать пул соединений через mysql.createPool используя библиотеку https://www.npmjs.org/package/mysql чтобы не случилось, что какое-то занято на долго запросом, а другое в ассинхронном режиме пришло и хочет быть обработано, пока предыдущее еще не вернулось. На событие разрыва соединения нужно навешивать его возобновление. Для случая с одним соединением так (для пула это нужно навесить на каждый конекшен:
    var mysql = require('mysql');
    connectMySql();
    
    function connectMySql() {
        var connection = mysql.createConnection(connectionString);
    
        connection.connect(function(err) {
            if (err) {
                setTimeout(function() {
                    connectMySql()
                }, 3000);
            }
        });
    
        connection.on('error', function(err) {
            if (err.code === 'PROTOCOL_CONNECTION_LOST') connectMySql();
        });
    }

    Если у вас небольшое приложение, то не стесняйтесь сделать конекшен или пул глобальным, чтобы он был сразу определен на обработчиках, а еще лучше сделайте для своего приложения неймспейс в глобальном контексте, например myApp = {} и в него запишите myApp.db = connection чтобы потом писать myApp.db.query(...); Посмотрите, какие красивые и лаконичные обработчики можно сделать, если не вестись на эти REST-суеверия и предубеждения против состояния на сервере и открытых долго конекшенов к БД и глобальных неймспейсов:
    // Обработчик для API по урлу http://127.0.0.1/example/app/examples/mysql/getCities.json
    module.exports = function(client, callback) {
      aliasNameMy.query('select * from City', function(err, rows, fields) {
        callback({ rows:rows, fields:fields });
      });
    }

    На гитхабе этот обработчик в контексте демо-приложения: https://github.com/tshemsedinov/impress/blob/maste...

    Ну и еще порекомендую свои утилиты для драйвера MySQL - https://www.npmjs.org/package/mysql-utilities
    и две статьи на Хабре, одну по этим утилитам - habrahabr.ru/post/198738 , а вторую по архитектуре в целом - habrahabr.ru/post/204958
    Ответ написан
    2 комментария
  • Универсальная обработка запросов в NodeJS. Какие варианты?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Универсального способа быть не может, потому, что все фреймворки имеют свою архитектуру и свою философию.
    Ответ написан
    Комментировать
  • Почему не устанавливается zmq для nodejs?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Проверьте, есть ли Visual Studio чтобы компилировать С++
    Присылаю еще вывод в консоль при правильной сборке, может пригодиться:
    D:\ab>npm install zmq
    /
    > zmq@2.8.0 install D:\ab\node_modules\zmq
    > node-gyp rebuild
    
    D:\ab\node_modules\zmq>node "C:\Program Files\nodejs\node_modules\npm\bin\node-g
    yp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild
    Построение проектов в этом решении по одному. Чтобы включить параллельное построение, добавьте параметр "/m". binding.cc
    C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xlocale(323): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    D:\ab\node_modules\zmq\node_modules\nan\nan.h(1221): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    D:\ab\node_modules\zmq\node_modules\nan\nan.h(1247): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(367): warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(564): warning C4344: behavior change: use of explicit template arguments results in call to 'v8::Local<T> NanNew<v8::String,char*>(P)' [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    with [ T=v8::String, P=char * ] but the regular function 'v8::Local<T> NanNew(const char *,int)' is a better match
    with [ T=v8::String ] if you expect 'v8::Local<T> NanNew(const char *,int)' to be called then you need to make it an explicit specialization
    with [ T=v8::String ]
    ..\binding.cc(590): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(591): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(592): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(593): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(594): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(595): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(596): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(597): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(598): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(599): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(614): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(615): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(616): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(617): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(618): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(619): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(620): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(621): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(622): warning C4244: 'argument' : conversion from 'int64_t' to 'const int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(623): warning C4244: 'argument' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(957): warning C4244: '=' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(1049): warning C4244: '=' : conversion from 'int64_t' to 'int', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(1136): warning C4344: behavior change: use of explicit template arguments results in call to 'v8::Local<T> NanNew<v8::String,char*>(P)' [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    with [ T=v8::String, P=char * ] but the regular function 'v8::Local<T> NanNew(const char *,int)' is a better match
    with [ T=v8::String ] if you expect 'v8::Local<T> NanNew(const char *,int)' to be called then you need to make it an explicit specialization
    with [ T=v8::String ]
    D:\ab\node_modules\zmq\node_modules\nan\nan.h(1036): warning C4244: 'argument': conversion from 'int64_t' to 'int32_t', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(540) : see reference to function template instantiation 'v8::Local<T> NanNew<v8::Integer,__int64>(P)' being compiled
    with [ T=v8::Integer, P=int64_t ]
    ..\binding.cc(595) : see reference to function template instantiation 'v8::Handle<T> zmq::Socket::GetSockOpt<int64_t>(int)' being compiled
    with [ T=v8::Value ]
    D:\ab\node_modules\zmq\node_modules\nan\nan.h(1036): warning C4244: 'argument': conversion from 'uint64_t' to 'int32_t', possible loss of data [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    ..\binding.cc(540) : see reference to function template instantiation 'v8::Local<T> NanNew<v8::Integer,unsigned __int64>(P)' being compiled
    with [ T=v8::Integer, P=uint64_t ]
    ..\binding.cc(597) : see reference to function template instantiation 'v8::Handle<T> zmq::Socket::GetSockOpt<uint64_t>(int)' being compiled
    with [ T=v8::Value ]
    C:\Users\Timur\.node-gyp\0.10.32\deps\v8\include\v8.h(179): warning C4506: no definition for inline function 'v8::Persistent<T> v8::Persistent<T>::New(v8::Handle<T>)' [D:\ab\node_modules\zmq\build\zmq.vcxproj]
    with [ T=v8::Object ]
    Creating library D:\ab\node_modules\zmq\build\Release\zmq.lib and object D:\ab\node_modules\zmq\build\Release\zmq.exp Generating code Finished generating code zmq.vcxproj -> D:\ab\node_modules\zmq\build\Release\\zmq.node
    zmq@2.8.0 node_modules\zmq
    +-- bindings@1.1.1
    L-- nan@1.3.0
    Ответ написан
    Комментировать
  • Как правильно сделать Transform Stream?

    MarcusAurelius
    @MarcusAurelius Куратор тега Node.js
    автор Impress Application Server для Node.js
    Не оттуда наследуете, смотрите пример в исходниках ноды в /lib/crypto.js
    Например класс Hash так написан, он наследует LazyTransform, вот так: util.inherits(Hash, LazyTransform); потом LazyTransform наследует от stream.Transform вот так: util.inherits(LazyTransform, stream.Transform); и потом определен метод _transform
    Hash.prototype._transform = function(chunk, encoding, callback) {
      this._binding.update(chunk, encoding);
      callback();
    };
    Ответ написан