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?
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 fakeapp
idatabase
params i testować tylko kodRoutes
. - 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.
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.
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.
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.
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();
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