2012-04-10 8 views
86

Voglio dividere i miei percorsi in file diversi, dove un file contiene tutti i percorsi e l'altro le azioni corrispondenti. Al momento ho una soluzione per raggiungere questo obiettivo, tuttavia ho bisogno di rendere globale l'istanza dell'app per poterlo accedere nelle azioni. La mia configurazione attuale si presenta così:Express: come passare l'istanza app alle rotte da un file diverso?

app.js:

var express = require('express'); 
var app  = express.createServer(); 
var routes = require('./routes'); 

var controllers = require('./controllers'); 
routes.setup(app, controllers); 

app.listen(3000, function() { 
    console.log('Application is listening on port 3000'); 
}); 

routes.js:

exports.setup = function(app, controllers) { 

    app.get('/', controllers.index); 
    app.get('/posts', controllers.posts.index); 
    app.get('/posts/:post', controllers.posts.show); 
    // etc. 

}; 

controller/index.js:

exports.posts = require('./posts'); 

exports.index = function(req, res) { 
    // code 
}; 

controllori/messaggi .js:

exports.index = function(req, res) { 
    // code 
}; 

exports.show = function(req, res) { 
    // code 
}; 

Tuttavia, questa configurazione ha un grosso problema: ho un database e un'istanza di app che devo passare alle azioni (controller/*. Js). L'unica opzione che potrei pensare, è rendere entrambe le variabili globali che non è davvero una soluzione. Voglio separare i percorsi dalle azioni perché ho molti percorsi e li voglio in un posto centrale.

Qual è il modo migliore per passare variabili alle azioni ma separare le azioni dai percorsi?

+0

Come sembra il tuo controller.js? Forse puoi renderlo una funzione (invece di un oggetto) che può ricevere parametri. – mihai

+0

require ('controller') richiede controller/index.js. Tuttavia, una funzione non funzionerà perché uso l'oggetto nelle rotte (vedi routes.js) e quindi non posso passare argomenti ad esso, anche se è una funzione. –

risposta

81

Node.js supporta dipendenze circolari.
uso Making of dipendenze circolari invece di richiedere (' ./ percorsi) (APP) pulisce un sacco di codice e rende ogni modulo meno interdipendenti sul suo caricamento del file:


app.js

var app = module.exports = express(); //now app.js can be required to bring app into any file 

//some app/middleware setup, etc, including 
app.use(app.router); 

require('./routes'); //module.exports must be defined before this line 


percorsi/indice.js

var app = require('../app'); 

app.get('/', function(req, res, next) { 
    res.render('index'); 
}); 

//require in some other route files...each of which requires app independently 
require('./user'); 
require('./blog'); 


----- 04/2014 aggiornamento -----
Express 4.0 fissa il caso d'uso per individuare gli itinerari aggiungendo un metodo() express.router!
documentazione - http://expressjs.com/4x/api.html#router

Esempio dal loro nuovo generatore:
Scrivere il percorso:
https://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
Aggiunta/namespacing alla app: https://github.com/expressjs/generator/blob/master/templates/js/app.js#L24

Ci sono casi d'uso ancora per l'accesso app da altre risorse, le dipendenze così circolari sono ancora una soluzione valida.

+1

"meno interdipendente sul suo file di caricamento" - dipende dallo specifico * percorso file * del suo file di caricamento.È un accoppiamento molto stretto, quindi non fingere che non lo sia. –

+1

Basta fare molta attenzione (leggi: non fare ciò per cui ho lottato per l'ultima ora +) che in 'app.js' hai bisogno del file di routing _after_ esportando l'app. Le chiamate circolari 'require()' possono creare confusione, quindi assicurati di sapere [come funzionano] (http://nodejs.org/docs/latest/api/modules.html#modules_cycles)! – Nateowami

+0

Onestamente penso che la risposta di @Feng sull'utilizzo di req.app.get ('somekey') sia davvero una soluzione migliore e più pulita rispetto all'utilizzo delle dipendenze circulr. –

0

Per database separato Servizio di accesso ai dati che eseguirà tutto il DB con API semplice ed evitare lo stato condiviso.

Separazione di routes.setup come overhead. Preferirei invece posizionare un instradamento basato sulla configurazione. E configura i percorsi in .json o con annotazioni.

+0

Cosa intendi con un servizio di accesso ai dati? Come sarebbe? –

+0

Il mio vero file routes.js è molto più grande e usa il modulo express-namespaces. Come separeresti i percorsi dalle azioni? –

25

Come ho detto nei commenti, è possibile utilizzare una funzione come module.exports. Una funzione è anche un oggetto, quindi non devi modificare la sintassi.

app.js

var controllers = require('./controllers')({app: app}); 

controllers.js

module.exports = function(params) 
{ 
    return require('controllers/index')(params); 
} 

controllori/index.js

function controllers(params) 
{ 
    var app = params.app; 

    controllers.posts = require('./posts'); 

    controllers.index = function(req, res) { 
    // code 
    }; 
} 

module.exports = controllers; 
+0

È OK restituire un oggetto all'interno della funzione o è meglio così impostare i metodi come si fa nell'esempio? –

+0

Penso che entrambi gli approcci siano ok. – mihai

+0

Poiché ho molti metodi, preferirei impostarli come oggetto invece che manualmente. Funzionerebbe quando restituisco appena l'oggetto, ma non c'è una soluzione un po 'più piatta? I miei metodi effettivi sarebbero rientrati due volte ... –

144

Usa req.app, req.app.get('somekey')

L'appli La variabile di cationizzazione creata chiamando express() è impostata sugli oggetti richiesta e risposta.

Vedi: https://github.com/visionmedia/express/blob/76147c78a15904d4e4e469095a29d1bec9775ab6/lib/express.js#L34-L35

+0

Grazie. Penso che questo sia il modo migliore per accedere alle variabili impostate con app.set ('name', val); –

+4

Non dimenticare di chiamare 'app.set ('somekey', {})' in app.js – ankitjaininfo

+1

La mia unica lamentela su questo modo anche se mi piace è che quando stai provando a eseguire un'app.locals.authorized come tale (non in main.js): 'app.route ('/ something'). get (app.locals.authorized, function (req, res, next) {});' non è possibile perché è fuori dal req scopo. – gabeio

0

Supponiamo di avere una cartella denominata "contollers".

Nei tuoi app.js è possibile inserire questo codice:

console.log("Loading controllers...."); 
var controllers = {}; 

var controllers_path = process.cwd() + '/controllers' 

fs.readdirSync(controllers_path).forEach(function (file) { 
    if (file.indexOf('.js') != -1) { 
     controllers[file.split('.')[0]] = require(controllers_path + '/' + file) 
    } 
}); 

console.log("Controllers loaded..............[ok]"); 

... e ...

router.get('/ping', controllers.ping.pinging); 

nei tuoi controller forlder si avrà il file "ping.js" con questo codice:

exports.pinging = function(req, res, next){ 
    console.log("ping ..."); 
} 

Ed è questo ....

2

o semplicemente che:

var app = req.app 

all'interno del Middleware si sta utilizzando per queste vie. Mi piace:

router.use((req,res,next) => { 
    app = req.app; 
    next(); 
}); 
Problemi correlati