Usando Express, para pasar referencias de instancia única como un registrador y/o db a las rutas, veo tres opciones actualmente.
Primero es adjuntarlo al objeto de solicitud a través de un middleware:
app.use(function(req,res,next){ req.db = db; //this db comes from app.js context where you define it next(); });o en la aplicación como:
app.set('db', db) // db was previously set ... app.get('user/:id', users.getUser);luego, dentro de su función de ruta, llame para usar:
module.export.getUser = (req,res) { ... req.app.get('db').user.find(request.params.id)La siguiente forma es llamar a algún método de inicio en el controlador, es decir:
const users = require('user.js); ... //setup logger, setup db, then call: users.init(logger,db); // init method sets local logger/database inside user.jsLast es una variación de lo anterior que fuerza a init a suceder una vez cuando se requiere el módulo:
// setup db and logger, then later call: require('user.js')(db, logger) //not great style-wise by not having all requires near the top of docy en su user.js, configure su exportación así:
module.exports = (db, logger) => { // returning public functionsEsto es lo que realmente odio de Vanilla JS, e incluso de un marco como Express. Es parte de la razón por la cual los marcos como React son tan populares porque existen formas establecidas de hacer las cosas o al menos patrones comúnmente aceptados.
Ok, de vuelta al tema. ¿Cuál es la mejor práctica para pasar cosas de instancia única como un registrador y una base de datos a todas sus rutas/controladores? Uno de los anteriores o algo mejor?
Desafortunadamente, si busca "mejores prácticas expresas para enrutadores", obtendrá docenas de variaciones. ¿Hay alguna referencia/biblia goto? ¿Alguna guía de mejores prácticas o mejores patrones?
Gracias por cualquier consejo / comentario, Paul
índice.js
const express = require('express'); const app = express(); require('./startup/logging')(app); require('./startup/routes')(app); require('./startup/db')(); const config = require('./startup/config'); const server = app.listen(config.app.port, () => console.log(`Listening on port ${config.app.port}...`)); module.exports = server;inicio/registro.js
const morgan = require('morgan'); module.exports = function (app) { app.use(morgan('tiny')); }inicio/base de datos
const mongoose = require('mongoose'); const config = require('./config'); module.exports = function () { mongoose.connect(config.db.uri, config.db.parameters) .then(() => console.log(`Connected to ${config.db.uri}...`)); }inicio/config.js
require('dotenv').config(); const env = process.env.NODE_ENV || 'dev'; const config = { 'dev': { app: { port: parseInt(process.env.DEV_APP_PORT), }, db: { uri: process.env.DEV_APP_DB, parameters: { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true } }, }, 'test': { app: { port: parseInt(process.env.TEST_APP_PORT), }, db: { uri: process.env.TEST_APP_DB, parameters: { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true } }, }, 'prod': { app: { port: parseInt(process.env.PROD_APP_PORT), }, db: { uri: process.env.PROD_APP_DB, parameters: { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true } }, } } module.exports = config[env];inicio/rutas.js
const express = require('express'); const users = require('user.js); module.exports = function (app) { app.use('/api/users', users); }rutas/usuarios.js
const auth = require('../middleware/auth'); const express = require('express'); const router = express.Router(); router.get('/users', auth, async (req, res) => { res.send([{name: 'paul', name: 'john'}]); }); module.exports = router;middleware/autorización
require('dotenv').config(); const jwt = require('jsonwebtoken'); module.exports = function (req, res, next) { const token = req.header('x-auth-token'); if (!token) return res.status(401).send('Access denied. No token provided.'); try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); } catch (ex) { res.status(400).send('Invalid token.'); } }.dotenv
NODE_ENV = 'dev' DEV_APP_PORT = 5000 TEST_APP_PORT = 4000 PROD_APP_PORT = 3000 DEV_APP_DB = 'mongodb://localhost:27017/example_dev' TEST_APP_DB = 'mongodb://localhost:27017/example_test' PROD_APP_DB = 'mongodb://localhost:27017/example' JWT_SECRET = 'yourJwtSecretKey'Estoy confundido en cuanto a por qué querría realizar una inyección de dependencia a través del marco de enrutamiento. Siempre he pensado en ellos como dos capas completamente separadas, expreso que se ocupa de las solicitudes http y luego delega a la lógica subyacente. Donde esa lógica puede ser un contenedor IOC de módulos DI o lo que quieras. En JS puede crear clases que requieren dependencias y luego módulos que exportan implementaciones de esas dependencias. Los módulos serán impls únicos de esas dependencias, lo que te permitirá hacer girar los combos que quieras. Sí, no creo que Express deba saber nada sobre su arquitectura o dependencias, simplemente debe asignar rutas a las funciones de la capa de servicio.