Variabile globale in app.js accessibile nei percorsi?


91

Come faccio a impostare una variabile in app.jse renderla disponibile in tutte le rotte, almeno nel index.jsfile che si trova nelle rotte. utilizzando il framework express enode.js


1
L' oggetto app.locals ha proprietà che sono variabili locali all'interno dell'applicazione. Nel file del percorso, fare riferimento ad esso con req.app.locals.
Ronnie Royston

Risposte:


65

Per creare una variabile globale, è sufficiente dichiararla senza la varparola chiave. (In generale questa non è una best practice, ma in alcuni casi può essere utile: fai solo attenzione perché renderà la variabile disponibile ovunque.)

Ecco un esempio da visionmedia / screenshot-app

file app.js :

/**
 * Module dependencies.
 */

var express = require('express')
  , stylus = require('stylus')
  , redis = require('redis')
  , http = require('http');

app = express();

//... require() route files

file route / main.js

//we can now access 'app' without redeclaring it or passing it in...

/*
 * GET home page.
 */

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

//...

6
Come nota, in genere è meglio essere espliciti sul passaggio di variabili e istanziarle, in modo da non annullare accidentalmente il riferimento da qualche altra parte nell'app o cosa hai.
Paul

3
Questa è davvero una brutta forma, come ha notato Paul. Suggerirei il modello di iniezione menzionato di seguito. Sì, più codice della piastra della caldaia quindi non sembra "carino" ma garantisce che il tuo codice sia modulare ... qualcosa che ti piacerà se questo non è il tuo ultimo progetto;)
srquinn

Dipende dalle circostanze IMHO. Sì, le variabili globali non sono generalmente una buona pratica (come ho affermato nella mia risposta) e quando si inizia da zero, direi di organizzare tutto in moduli separati. Ma se ti stai integrando con il codice esistente, ci sono spesso altre considerazioni: questa è solo una soluzione (facile, ma pericolosa).
Jesse Fulton

2
Qualcuno potrebbe spiegare perché funziona in riferimento alla semantica di Javascript? A quale ambito appviene associato?
Ali

Non credo che questa risposta debba essere contrassegnata come correctuna.
Code Cooker

93

In realtà è molto facile farlo utilizzando i metodi "set" e "get" disponibili su un oggetto express.

Esempio come segue, supponi di avere una variabile chiamata config con le tue cose relative alla configurazione che vuoi essere disponibile in altri posti:

In app.js:

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

app.configure(function() {
  ...
  app.set('config', config); 
  ...
}

In route / index.js

exports.index = function(req, res){
  var config = req.app.get('config');
  // config is now available
  ...
}

Impostare "app" globale? Sì. Ma questo metodo è il migliore per salvarci da problemi e caos.
diproart

53
per i ritardatari: app.configure è stato rimosso in express 4.x
zamil

Bello, req.app.get('name')funziona come un incantesimo. Questa proprietà contiene un riferimento all'istanza dell'applicazione Express che utilizza il middleware. expressjs.com/pt-br/api.html#req.app
Lazaro Fernandes Lima Suleiman

57

Un modo accurato per farlo è utilizzare app.localsfornito da Express stesso. Ecco la documentazione.

// In app.js:
app.locals.variable_you_need = 42;

// In index.js
exports.route = function(req, res){
    var variable_i_needed = req.app.locals.variable_you_need;
}

1
Ho utilizzato questo metodo per individuare i servizi http e sovrascriverli facilmente negli unit test.
Alex

28

Per dichiarare una variabile globale è necessario utilizzare l' oggetto globale . Come global.yourVariableName. Ma non è vero. Per condividere le variabili tra i moduli, prova a utilizzare lo stile di iniezione come

someModule.js:

module.exports = function(injectedVariable) {
    return {
        somePublicMethod: function() {
        },
        anotherPublicMethod: function() {
        },
    };
};

app.js

var someModule = require('./someModule')(someSharedVariable);

Oppure puoi usare un oggetto surrogato per farlo. Come hub .

someModule.js:

var hub = require('hub');

module.somePublicMethod = function() {
    // We can use hub.db here
};

module.anotherPublicMethod = function() {
};

app.js

var hub = require('hub');
hub.db = dbConnection;
var someModule = require('./someModule');

7

Ecco spiegati bene, in breve:

http://www.hacksparrow.com/global-variables-in-node-js.html

Quindi stai lavorando con una serie di moduli Node, forse un framework come Express.js, e improvvisamente senti il ​​bisogno di rendere alcune variabili globali. Come si rendono globali le variabili in Node.js?

Il consiglio più comune a questo è di "dichiarare la variabile senza la parola chiave var" o "aggiungere la variabile all'oggetto globale" o "aggiungere la variabile all'oggetto GLOBAL". Quale usi?

Prima di tutto, analizziamo l'oggetto globale. Apri un terminale, avvia un nodo REPL (prompt).

> global.name
undefined
> global.name = 'El Capitan'
> global.name
'El Capitan'
> GLOBAL.name
'El Capitan'
> delete global.name
true
> GLOBAL.name
undefined
> name = 'El Capitan'
'El Capitan'
> global.name
'El Capitan'
> GLOBAL.name
'El Capitan'
> var name = 'Sparrow'
undefined
> global.name
'Sparrow'

In Express, quando si usa jshint o linting, in generale, questo diventa un problema.
Steven Ventimiglia

6

il modo più semplice è dichiarare una variabile globale nel tuo app.js, all'inizio:

global.mySpecialVariable = "something"

quindi in qualsiasi percorso puoi ottenerlo:

console.log(mySpecialVariable)

1
In Express, quando si usa jshint o linting, in generale, questo diventa un problema.
Steven Ventimiglia

5

Questa era una domanda utile, ma potrebbe esserlo di più fornendo esempi di codice reali. Anche l'articolo collegato non mostra effettivamente un'implementazione. Pertanto, sottometto umilmente:

Nel tuo app.jsfile, all'inizio del file:

var express = require('express')
, http = require('http')
, path = require('path');

app = express(); //IMPORTANT!  define the global app variable prior to requiring routes!

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

app.js non avrà alcun riferimento al app.get()metodo. Lascia che siano definiti nei singoli file delle rotte.

routes/index.js:

require('./main');
require('./users');

e, infine, un file percorsi vero e proprio, routes/main.js:

function index (request, response) {
    response.render('index', { title: 'Express' });
}

app.get('/',index); // <-- define the routes here now, thanks to the global app variable

4

Il mio modo preferito è usare le dipendenze circolari *, supportate dal nodo

  • in app.js definisci var app = module.exports = express();come il tuo primo ordine del giorno
  • Ora qualsiasi modulo richiesto dopo il fatto può var app = require('./app')accedervi


app.js

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

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

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


rotte / index.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');

Ottimo suggerimento. Sono passato dal metodo require ('./ myroutes') (app) a farlo e ho sbattuto la testa contro un muro per 10 minuti cercando di capire perché nessuna delle mie rotte funzionava. Non dimenticare di estrarre le specifiche del percorso in myroutes.js da un blocco funzione. Doh!
greg

2

Come altri hanno già condiviso, app.set('config', config)è ottimo per questo. Volevo solo aggiungere qualcosa che non ho visto nelle risposte esistenti che è abbastanza importante. Un'istanza di Node.js è condivisa tra tutte le richieste, quindi, sebbene possa essere molto pratico condividere alcuni configo routeroggetti a livello globale, l' archiviazione dei dati di runtime a livello globale sarà disponibile tra richieste e utenti . Considera questo esempio molto semplice:

var express = require('express');
var app = express();

app.get('/foo', function(req, res) {
    app.set('message', "Welcome to foo!");
    res.send(app.get('message'));
});

app.get('/bar', function(req, res) {
    app.set('message', "Welcome to bar!");

    // some long running async function
    var foo = function() {
        res.send(app.get('message'));
    };
    setTimeout(foo, 1000);
});

app.listen(3000);

Se visiti /bare /fooarriva un'altra richiesta , il tuo messaggio sarà "Welcome to foo!". Questo è un esempio sciocco, ma fa capire il punto.

Ci sono alcuni punti interessanti al riguardo in Perché diverse sessioni di node.js condividono variabili? .


1

Ho risolto lo stesso problema, ma ho dovuto scrivere più codice. Ho creato un server.jsfile, che usa express per registrare le rotte. Espone una funzione, registerche può essere utilizzata da altri moduli per registrare i propri percorsi. Espone anche una funzione,, startServerper iniziare ad ascoltare una porta

server.js

const express = require('express');
const app = express();

const register = (path,method,callback) => methodCalled(path, method, callback)

const methodCalled = (path, method, cb) => {
  switch (method) {
    case 'get':
      app.get(path, (req, res) => cb(req, res))
      break;
    ...
    ...  
    default:
      console.log("there has been an error");
  }
}

const startServer = (port) => app.listen(port, () => {console.log(`successfully started at ${port}`)})

module.exports = {
  register,
  startServer
}

In un altro modulo, usa questo file per creare una rotta.

help.js

const app = require('../server');

const registerHelp = () => {
  app.register('/help','get',(req, res) => {
    res.send("This is the help section")
  }),
  app.register('/help','post',(req, res) => {
    res.send("This is the help section")
  })}

module.exports = {
  registerHelp
}

Nel file principale, avvia entrambi i file.

app.js

require('./server').startServer(7000)
require('./web/help').registerHelp()

0

La risposta di John Gordon è stata la prima di dozzine di risposte parzialmente spiegate / documentate che ho provato, da molti, molti siti, che hanno effettivamente funzionato. Grazie signor Gordon. Scusa, non ho i punti per spuntare la tua risposta.

Vorrei aggiungere, per altri neofiti di node-route-file-splitting, che l'uso della funzione anonima per 'index' è ciò che si vedrà più spesso, quindi usando l'esempio di John per main.js, il funzionalmente- il codice equivalente che si troverebbe normalmente è:

app.get('/',(req, res) {
    res.render('index', { title: 'Express' });
});

0

Ho usato app.all

Il metodo app.all () è utile per mappare la logica "globale" per prefissi di percorso specifici o corrispondenze arbitrarie.

Nel mio caso, sto usando confit per la gestione della configurazione,

app.all('*', function (req, res, next) {
    confit(basedir).create(function (err, config) {
        if (err) {
            throw new Error('Failed to load configuration ', err);
        }
        app.set('config', config);
        next();
    });
});

Nelle rotte, lo fai semplicemente req.app.get('config').get('cookie');


0

questa è una cosa abbastanza facile, ma le risposte delle persone sono confuse e complesse allo stesso tempo.

lascia che ti mostri come puoi impostare la variabile globale nella tua expressapp. Quindi puoi accedervi da qualsiasi percorso secondo necessità.

Diciamo che vuoi impostare una variabile globale dalla tua /rotta principale

router.get('/', (req, res, next) => {

  req.app.locals.somethingNew = "Hi setting new global var";
});

Quindi otterrai req.app da tutti i percorsi. e poi dovrai usare il localsper impostare i dati globali in. come sopra mostra che sei pronto. ora ti mostrerò come utilizzare quei dati

router.get('/register', (req, res, next) => {

  console.log(req.app.locals.somethingNew);
});

Come sopra dal registerpercorso a cui stai accedendo ai dati è stato impostato in precedenza.

È così che puoi far funzionare questa cosa!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.