Простой Dependency Injection в Node.js

в 15:08, , рубрики: dependency injection, javascript, node.js, ооп

Прочитав несколько статей на тему DI мне захотелось использовать его в Node.js; после недолгих поисков оказалось, что модулей для этого не так много, из них самый интересный — di.js от Angular, но он мне не подошел и я решил написать свой.

Почему не di.js?

  • он написан с использованием ES6, т.е. нуждается в предварительной компиляции в ES5, а так как он использует декораторы, то и ваш код должен быть скомпилирован в ES5
  • давно не поддерживается
  • использует старый компилятор (es6-shim)
  • нет возможности создавать несколько инстансов одного класса

Пишем свою реализацию

Самой интересной в написании модуля оказалась задача динамической передачи в конструктор аргументов.
Наиболее очевидное решение — использовать apply, но это не сработает, так как он взаимодействует с методами, а не конструкторами.

Для нашей цели можно воспользоваться spread operator:

class Test {
    constructor(a, b) {

    }
}

let args = [1, 2]
let test = new Test(...args)

В остальном реализация довольно скучна и не содержит ничего интересного.

Используем модуль

Я решил отказаться от декораторов di.js в пользу конфиг-файла. Допустим, мы описываем архитектуру компьютера, тогда в конфиге нам нужно описать наши классы, пути к ним и их аргументы:

{
  "Computer": {
    "class": "./Computer.js", // Путь к классу 
    "args": ["RAM", "HDD", "CPU", "GPU"] // Зависимости
  },
  "RAM": {
    "class": "./RAM.js",
    "args": []
  },
  "HDD": {
    "class": "./HDD.js",
    "args": []
  },
  "CPU": {
    "class": "./CPU.js",
    "args": ["RAM"]
  },
  "GPU": {
    "class": "./GPU.js",
    "args": []
  }
}

Класс Computer, как и все остальные, довольно простой:

'use strict'

class Computer {
    constructor(ram, hdd, cpu, gpu) {
        this._cpu = cpu
        this._gpu = gpu
        this._hdd = hdd
        this._ram = ram
    }
}

module.exports = Computer

Теперь в точке входа нашего приложения используем модуль:

const Injector = require('razr')(__dirname, './path/to/your/config.json') // передаем текущий путь и путь к конфигу

const computer = Injector.get('Computer') // тут мы молучим инстанс Computer

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

На этом все. Спасибо всем, кто дочитал. А вот ссылочка на GitHub — https://github.com/Naltox/razr и NPM — http://npmjs.com/package/razr

Автор: Altox

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js