2012-04-24 8 views
56

Utilizo archivos de enrutador separados como módulos para la aplicación principal y la aplicación de autenticación. No puedo obtener la mejor forma de pasar variables (cliente de db) a los enrutadores. No quiero a codificar o pasarlo con:¿Cuál es la mejor manera de pasar variables comunes en módulos separados en Node.js?

module.exports = function(app, db) { 

Tal vez sea mejor manera de utilizar Singleton registrarse o utilizar variable de base global?

¿Cuál es su experiencia con los patrones de diseño? ¿Cuál es la mejor y por qué?

+1

posible duplicar http://stackoverflow.com/questions/8931239/how-to-access-variables-declared-in-main-app-js-in-seperate-route-files-in-node/8931366 # 8931366 –

Respuesta

99

He encontrado el uso de la inyección de dependencia, para pasar cosas, para ser el mejor estilo. Sería ciertamente un aspecto similar tiene:

// 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. 

Esto tiene una serie de beneficios:

  • Te obliga a separar su sistema en componentes con dependencias claras, en lugar de ocultar las dependencias en algún lugar del medio del archivo donde llaman require("databaseSingleton") o peor, global.database.
  • Hace las pruebas unitarias muy fáciles: si quiero probar Routes de forma aislada, puedo inyectarlo con los parámetros falsos app y database y probar solo el código Routes.
  • Junta todos los cables de objetos y gráficos en un solo lugar, es decir, la raíz de la composición (que en este caso es server.js, el punto de entrada de la aplicación). Esto le brinda un lugar único para observar cómo encaja todo en el sistema.

Una de las mejores explicaciones para esto que yo he visto es an interview with Mark Seeman, autor del excelente libro inyección de dependencias en .NET. Se aplica tanto a JavaScript, y especialmente a Node.js: require a menudo se utiliza como un localizador de servicios clásico, en lugar de solo un sistema de módulos.

+0

Estoy tratando de utilizar este ejemplo, sin embargo, ¿cómo defino mis rutas en su implementación de Routes.js ya que está dentro de esta función de Rutas? ¡Gracias! – cpeele00

+0

@ cpeele00 de la misma manera que lo haría con los métodos de otras clases. – Domenic

+0

Al utilizar esta configuración, ¿separa sus rutas de manera similar? p.ej. Rutas (aplicación, base de datos) {routes = {sociales: nuevas SocialRoutes (aplicación, base de datos), api: nuevas ApiRoutes (aplicación, base de datos)}; rutas de regreso; } – Stephen

2

Le sugiero que cree un archivo de configuración con instancia db y con otras cosas que necesita utilizar globalmente como 'singleton'.

Por ejemplo, he settings.js con mi cliente Redis db:

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

Y en otros múltiples módulos de E incluirlo:

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

Muchas veces incluyéndola siempre tengo un caso de la conexión db.

+0

Si uso el siguiente código: ' var redis = require ('redis'); var client = redis.createClient (6379, '127.0.0.1'); client.auth (redispass); exports.client = client; ' ¿Este módulo volverá a conectar redis una y otra vez, o no? – Serg

+2

no, solo una conexión. Busque [documentación] (http://nodejs.org/api/modules.html#modules_caching), _Múltiples llamadas a require ('foo') pueden no causar que el código del módulo se ejecute varias veces_ – akaravashkin

+3

Es arriesgado confiar en " requiere "para el comportamiento de singleton, ya que solo obtendrá la misma instancia si pasa exactamente la misma ruta. Los módulos se almacenan en caché según la ruta pasada, no en una ruta resuelta. En otras palabras, funcionará como singleton, hasta que intente usarlo desde un subdirectorio. –

0

es completamente obsoleta, pero se puede utilizar global en un script:

global.foo = new Foo(); 

en otro script:

foo.bar(); 

También puede utilizar constante ya existente:

Object.foo = new Foo(); 

Y aquí:

Object.foo.bar(); 
1

usted puede ahorrarse todo el código estándar de cableado de su módulos si se utiliza un marco de inyección de dependencias

This answer listas de algunos de ellos. También construí un simpler DI framework here.

EDIT: A continuación se muestra una copia forman la respuesta en caso de que la página cambia


require es la forma de gestionar dependencias en Node.js la que ciertamente es intuitiva y eficaz, pero tiene también sus limitaciones.

Mi consejo es echar un vistazo a algunos de los contenedores de Inyección de Dependencia disponibles hoy para Node.js para tener una idea de cuáles son sus ventajas y desventajas. Algunos de ellos son:

sólo para nombrar unos pocos.

Ahora la verdadera pregunta es, ¿qué se puede lograr con un contenedor DI Node.js, en comparación con un simple require?

Pros:

  • mejor capacidad de prueba: módulos acepta sus dependencias como entrada
  • Inversión de Control: decidir cómo conectar los módulos sin tocar el código principal de su aplicación.
  • algoritmo personalizable para resolver módulos: las dependencias tienen identificadores "virtuales", por lo general no están vinculados a una ruta en el sistema de archivos.
  • Mejor extensibilidad: habilitada por IoC e identificadores "virtuales".
  • Otras cosas de lujo posible:
    • asíncrono inicialización
    • gestión del ciclo de vida del módulo
    • extensibilidad del propio contenedor DI
    • se puede implementar fácilmente abstracciones de nivel superior (por ejemplo, AOP)

Contras:

  • Diferente de la "experiencia" de Node.js: no usar require definitivamente parece que se está desviando de la forma de pensar del nodo.
  • La relación entre una dependencia y su implementación no siempre es explícita. Una dependencia puede resolverse en tiempo de ejecución e influenciada por diversos parámetros. El código se vuelve más difícil de entender y depurar
  • lento tiempo de arranque
  • Madurez (por el momento): ninguna de las soluciones actuales es realmente popular en este momento, por lo que no muchos tutoriales, ningún ecosistema, no batalla probado
  • Algunos contenedores DI no funcionarán bien con los paquetes de módulos como Browserify y Webpack.
Cuestiones relacionadas