Нужно ли вводить зависимости в NodeJS или как бороться с ...? - PullRequest
188 голосов
/ 12 февраля 2012

Я сейчас создаю несколько экспериментальных проектов с помощью nodejs. Я программировал множество веб-приложений на Java EE с помощью Spring и оценил простоту внедрения зависимостей.

Теперь мне любопытно: как сделать внедрение зависимостей с помощью узла? Или: мне это вообще нужно? Есть ли замена концепции, потому что стиль программирования отличается?

Я пока говорю о простых вещах, таких как совместное использование объекта подключения к базе данных, но я не нашел решения, которое меня устраивало.

Ответы [ 21 ]

2 голосов
/ 27 января 2017

Для ES6 я разработал этот контейнер https://github.com/zazoomauro/node-dependency-injection

import {ContainerBuilder} from 'node-dependency-injection'

let container = new ContainerBuilder()
container.register('mailer', 'Mailer')

Затем вы можете установить, например, выбор транспорта в контейнере:

import {ContainerBuilder} from 'node-dependency-injection'

let container = new ContainerBuilder()
container
  .register('mailer', 'Mailer')
  .addArgument('sendmail')

Этот класс теперьгораздо гибче, поскольку вы разделили выбор транспорта из реализации и в контейнер.

Теперь, когда служба почтовых программ находится в контейнере, вы можете внедрить ее как зависимость от других классов.Если у вас есть класс NewsletterManager, подобный следующему:

class NewsletterManager {
    construct (mailer, fs) {
        this._mailer = mailer
        this._fs = fs
    }
}

export default NewsletterManager

При определении службы newsletter_manager служба почтовой рассылки еще не существует.Используйте класс Reference, чтобы указать контейнеру внедрить службу почтовой программы при инициализации менеджера новостной рассылки:

import {ContainerBuilder, Reference, PackageReference} from 'node-dependency-injection'
import Mailer from './Mailer'
import NewsletterManager from './NewsletterManager'

let container = new ContainerBuilder()

container
  .register('mailer', Mailer)
  .addArgument('sendmail')

container
  .register('newsletter_manager', NewsletterManager)
  .addArgument(new Reference('mailer'))
  .addArgument(new PackageReference('fs-extra'))

Вы также можете настроить контейнер с файлами конфигурации, такими как файлы Yaml, Json или JS

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

container.compile()
1 голос
/ 14 июня 2015

Google's di.js работает на nodejs (+ браузер) (+ ​​ES6)

1 голос
/ 20 января 2014

Взгляните на провалы (простая, но мощная инфраструктура внедрения зависимостей и сущностей (файлов) для Node.js)

https://github.com/devcrust/node-dips

1 голос
/ 12 февраля 2012

Это зависит от дизайна вашего приложения.Очевидно, что вы можете выполнить Java-инъекцию, где вы создаете объект класса с зависимостью, передаваемой в конструктор, как это.

function Cache(store) {
   this._store = store;
}

var cache = new Cache(mysqlStore);

Если вы не выполняете ООП в javascript, вы можете сделать функцию initкоторый все настраивает.

Однако есть другой подход, который вы можете использовать, который более распространен в системе, основанной на событиях, такой как node.js.Если вы можете смоделировать ваше приложение только для того, чтобы (в большинстве случаев) воздействовать на события, тогда все, что вам нужно сделать, это настроить все (что я обычно делаю, вызывая функцию init) и генерировать события из заглушки.Это делает тестирование довольно простым и читабельным.

0 голосов
/ 20 мая 2017

Я обнаружил этот вопрос, когда отвечал на вопрос в моем собственном модуле DI, спрашивающий, зачем когда-либо понадобится система DI для программирования NodeJS.

Ответ явно был нацелендано в этой теме: это зависит.Для обоих подходов есть компромиссы, и чтение ответов на этот вопрос дает им хорошую форму.

Таким образом, реальный ответ на этот вопрос должен заключаться в том, что в некоторых ситуациях вы должны использовать систему DI, вдругие нет.

Тем не менее, вы, как разработчик, не хотите повторяться и повторно использовать ваши сервисы в различных приложениях.

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

module.exports = initDBService;

// Tells any DI lib what it expects to find in it context object
// The $inject prop is the de facto standard for DI imo 
initDBService.$inject = ['ENV'];

// Note the context object, imo, a DI tool should bring
// services in a single context object
function initDBService({ ENV }) {
/// actual service code
}

Таким образом, ваш сервис будет работать независимо от того, используете ли вы его с инструментом DI или без него.

0 голосов
/ 11 июля 2017

Я работал с .Net, PHP и Java в течение длительного времени, поэтому я хотел иметь удобное внедрение зависимостей и в NodeJS.Люди сказали, что встроенного DI в NodeJS достаточно, поскольку мы можем получить его с помощью Module.Но это не удовлетворило меня хорошо.Я хотел сохранить модуль не более, чем класс.Кроме того, я хотел, чтобы DI имел полную поддержку управления жизненным циклом модуля (одноэлементный модуль, переходный модуль и т. Д.), Но с модулем Node мне приходилось очень часто писать ручной код.Наконец, я хотел облегчить юнит тест.Вот почему я создал инъекцию зависимостей для себя.

Если вы ищете DI, попробуйте.Его можно найти здесь: https://github.com/robo-creative/nodejs-robo-container. Это полностью задокументировано.В нем также рассматриваются некоторые распространенные проблемы с DI и способы их решения ООП.Надеюсь, это поможет.

0 голосов
/ 31 декабря 2013

Я недавно создал библиотеку под названием circuitbox , которая позволяет вам использовать внедрение зависимостей с node.js. Он действительно внедряет зависимости по сравнению со многими библиотеками на основе поиска зависимостей, которые я видел. Circuitbox также поддерживает процедуры асинхронного создания и инициализации. Ниже приведен пример:

Предположим, что следующий код находится в файле с именем consoleMessagePrinter.js

'use strict';

// Our console message printer
// deps is injected by circuitbox with the dependencies
function ConsoleMessagePrinter(deps) {
  return {
    print: function () {
      console.log(deps.messageSource.message());
    }
  };
}

module.exports = ConsoleMessagePrinter;

Предположим, что следующее находится в файле main.js

'use strict';

// our simple message source
// deps is injected by circuitbox with the dependencies
var simpleMessageSource = function (deps) {
  return {
    message: function () {
      return deps.message;
    }
  };
};

// require circuitbox
var circuitbox = require('../lib');

// create a circuitbox
circuitbox.create({
  modules: [
    function (registry) {
      // the message to be used
      registry.for('message').use('This is the message');

      // define the message source
      registry.for('messageSource').use(simpleMessageSource)
        .dependsOn('message');

      // define the message printer - does a module.require internally
      registry.for('messagePrinter').requires('./consoleMessagePrinter')
        .dependsOn('messageSource');
    }
  ]
}).done(function (cbx) {

  // get the message printer and print a message
  cbx.get('messagePrinter').done(function (printer) {
    printer.print();
  }, function (err) {
    console.log('Could not recieve a printer');
    return;
  });

}, function (err) {
  console.log('Could not create circuitbox');
});

Circuitbox позволяет вам определять ваши компоненты и объявлять их зависимости как модули. После инициализации он позволяет вам получить компонент. Circuitbox автоматически вводит все компоненты, которые требуются целевому компоненту, и выдает его для использования.

Проект находится в альфа-версии. Ваши комментарии, идеи и отзывы приветствуются.

Надеюсь, это поможет!

0 голосов
/ 28 декабря 2016

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

Подробнее о KlarkJS

Краткий пример:

KlarkModule(module, 'myModuleName1', function($nodeModule1, myModuleName2) {
    return {
        log: function() { console.log('Hello from module myModuleName1') }
    };
});
  • myModuleName1 - название модуля.
  • $nodeModule1 - это внешняя библиотека из node_module. Имя разрешается до node-module1. Префикс $ указывает, что это внешний модуль.
  • myModuleName2 - это имя внутреннего модуля.
  • Возвращаемое значение контроллера используется другими внутренними модулями, когда они определяют параметр myModuleName1.
0 голосов
/ 21 октября 2016

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

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

Одним из решений будет передача зависимостей в качестве параметров модуля:

module.exports = function (dep1, dep2) {
// private methods

   return {
    // public methods
       test: function(){...}
   }
}

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

Существуют и другие решения (бродвей, архитектор и т. Д.), Которые могут помочь вам в этом.хотя они могут делать больше, чем вы хотите, или использовать больше беспорядка.

0 голосов
/ 23 июня 2016

Это должно быть гибким и простым, как это:

var MyClass1 = function () {}
var MyClass2 = function (myService1) {
    // myService1.should.be.instanceof(MyClass1); 
}


container.register('myService1', MyClass1);
container.register('myService2', MyClass2, ['myService1']);

Я написал статью о внедрении зависимостей в node.js.

Надеюсь, это поможет вам в этом.

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