Jaki jest najlepszy sposób przekazywania wspólnych zmiennych do oddzielnych modułów w węźle.js?

Używam oddzielnych plików routera jako modułów dla aplikacji głównej i aplikacji auth. Nie mogę znaleźć najlepszego sposobu przekazywania zmiennych (db client) do routerów. Nie chcę tego hardcodować ani przekazywać:

module.exports = function(app, db) {

Może to najlepszy sposób na użycie singleton register lub użycie globalnej zmiennej db?

Jakie jest twoje doświadczenie z wzorcami projektowymi? Która droga jest najlepsza i dlaczego?

Author: Flip, 2012-04-25

4 answers

Uznałem użycie dependency injection, aby przekazać rzeczy, być najlepszym stylem. Rzeczywiście wyglądałoby to tak jak ty:

// App.js
module.exports = function App() {
};

// Database.js
module.exports = function Database(configuration) {
};

// Routes.js
module.exports = function Routes(app, database) {
};

// server.js: composition root
var App = require("./App");
var Database = require("./Database");
var Routes = require("./Routes");
var dbConfig = require("./dbconfig.json");

var app = new App();
var database = new Database(dbConfig);
var routes = new Routes(app, database);

// Use routes.

Ma to wiele zalet:

  • zmusza do rozdzielenia systemu na komponenty z wyraźnymi zależnościami, zamiast ukrywać zależności gdzieś w środku pliku, do którego wywołują require("databaseSingleton") lub gorzej, global.database.
  • sprawia, że testowanie jednostkowe jest bardzo proste: jeśli chcę przetestować Routes w izolacji, mogę wstrzyknąć go z fake app i database params i testować tylko kod Routes.
  • umieszcza wszystkie okablowanie grafu Obiektowego w jednym miejscu, a mianowicie korzeń kompozycji (który w tym przypadku jest server.js, punktem wejścia aplikacji). Daje to jedno miejsce do spojrzenia, aby zobaczyć, jak wszystko pasuje do siebie w systemie.

Jednym z lepszych wyjaśnień tego, co widziałem, jest wywiad z Markiem Seemanem , autorem znakomitej książki Dependency Injection in . NET . stosuje się tak samo do JavaScript, a zwłaszcza do Node.js: require jest często używany jako klasyczny lokalizator usług, a nie tylko system modułów.

 103
Author: Domenic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-26 06:31:32

Proponuję utworzyć plik ustawień z instancją db i innymi rzeczami, których potrzebujesz używać globalnie, takimi jak'singleton'.

Na przykład, mam ustawienia.js z moim klientem Redis db:

var redis = require('redis');
exports.redis = redis.createClient(6379, '127.0.0.1');

I w innych modułach dołączam GO:

var settings = require('./settings');
setting.redis.<...>

Wiele razy włączając to zawsze mam jedną instancję połączenia db.

 2
Author: akaravashkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-26 06:10:06

Możesz oszczędzić sobie całego kodu boilerplate okablowania swoich modułów, jeśli używasz struktury wtrysku zależności

Ta ODPOWIEDŹ wymienia kilka z nich. Zbudowałem również prostszy framework DI tutaj .

EDIT: poniżej jest kopia formularza odpowiedzi w przypadku zmiany strony


require jest sposobem zarządzania zależnościami w węźle.js i na pewno jest intuicyjny i skuteczny, ale ma też swoje ograniczenia.

Moja rada jest przyjrzenie się niektórym kontenerom iniekcji zależności dostępnym obecnie dla Node.js, aby mieć pomysł na to, jakie są ich plusy / minusy. Niektóre z nich to: Żeby wymienić tylko kilka. Teraz prawdziwe pytanie brzmi, co można osiągnąć z węzłem.kontener JS DI, w porównaniu do prostego require?

Plusy:

  • lepsza testowalność: Moduły akceptują swoje zależności jako dane wejściowe
  • Inwersja sterowania: zdecyduj, jak podłączyć moduły bez dotykania głównego kodu aplikacji.
  • konfigurowalny algorytm rozwiązywania modułów: zależności mają" wirtualne " identyfikatory, zwykle nie są one powiązane ze ścieżką w systemie plików.
  • lepsza rozszerzalność: włączona przez IoC I "wirtualne" identyfikatory.
  • inne fantazyjne rzeczy możliwe:
    • inicjalizacja asynchroniczna
    • zarządzanie cyklem życia modułu
    • rozszerzalność samego pojemnika DI
    • Może łatwo zaimplementować abstrakcje wyższego poziomu (np.]}

Wady:

  • różni się od węzła.js "experience": nieużywanie require zdecydowanie sprawia wrażenie, jakbyś odbiegał od sposobu myślenia węzła.
  • zależność między zależnością a jej implementacją nie zawsze jest wyraźnie. Zależność może być rozwiązywana w czasie wykonywania i zależna od różnych parametrów. Kod staje się trudniejszy do zrozumienia i debugowania
  • wolniejszy czas uruchamiania
  • dojrzałość (w tej chwili): żadne z obecnych rozwiązań nie jest naprawdę popularne w tej chwili, więc nie tak wiele tutoriali, nie ekosystem, nie testowane bitwy.
  • niektóre kontenery DI nie będą dobrze grać z pakietami modułów, takimi jak Browserify i Webpack.
 1
Author: Gaafar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:29

Jest całkowicie przestarzały, ale możesz użyć global w skrypcie:

 global.foo = new Foo();

W innym skrypcie:

 foo.bar();

Możesz również użyć już istniejącej stałej:

 Object.foo = new Foo();

I tutaj:

 Object.foo.bar();
 0
Author: Vinz243,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-23 16:55:11