Variable globale dans app.js accessible dans les itinéraires?

91

Comment définir une variable dans app.jset la rendre disponible dans toutes les routes, au moins dans le index.jsfichier situé dans routes. en utilisant le framework express etnode.js

Technupe
la source
1
L' objet app.locals a des propriétés qui sont des variables locales dans l'application. Dans votre fichier d'itinéraire, référencez-le avec req.app.locals.
Ronnie Royston

Réponses:

65

Pour créer une variable globale, déclarez-la simplement sans le varmot clé. (En règle générale, ce n'est pas la meilleure pratique, mais dans certains cas, cela peut être utile - faites simplement attention car cela rendra la variable disponible partout.)

Voici un exemple de visionmedia / screenshot-app

fichier app.js :

/**
 * Module dependencies.
 */

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

app = express();

//... require() route files

fichiers routes / 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');
});

//...
Jesse Fulton
la source
6
À titre de note, il est généralement préférable d'être explicite sur le passage des variables et leur instanciation, afin de ne pas annuler accidentellement la référence ailleurs dans l'application, ou quoi que ce soit.
Paul
3
C'est vraiment une mauvaise forme, comme l'a noté Paul. Je suggérerais le modèle d'injection mentionné ci-dessous. Oui, plus de code de plaque chauffante pour ne pas avoir l'air "joli" mais cela garantit que votre code est modulaire ... quelque chose que vous aimerez si ce n'est pas votre dernier projet;)
srquinn
Cela dépend des circonstances IMHO. Oui, les variables globales ne sont généralement pas une bonne pratique (comme je l'ai dit dans ma réponse) et en partant de zéro, je dirais que tout est organisé en modules séparés. Mais si vous intégrez du code existant, il y a souvent d'autres considérations - cela se trouve être une solution (facile, mais dangereuse).
Jesse Fulton
2
Quelqu'un pourrait-il expliquer pourquoi cela fonctionne en référence à la sémantique de Javascript? À quelle portée est- appil associé?
Ali
Je ne pense pas que cette réponse devrait être considérée comme telle correct.
Code Cooker
93

Il est en fait très facile de faire cela en utilisant les méthodes "set" et "get" disponibles sur un objet express.

Exemple comme suit, disons que vous avez une variable appelée config avec vos éléments liés à la configuration que vous souhaitez être disponibles ailleurs:

Dans app.js:

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

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

Dans routes / index.js

exports.index = function(req, res){
  var config = req.app.get('config');
  // config is now available
  ...
}
Mandy
la source
Définir 'app' global? Oui. Mais cette méthode est la meilleure pour nous sauver des problèmes et du chaos.
diproart
53
pour les retardataires: app.configure est supprimé dans express 4.x
zamil
Nice, req.app.get('name')fonctionne comme un charme. Cette propriété contient une référence à l'instance de l'application Express qui utilise le middleware. expressjs.com/pt-br/api.html#req.app
Lazaro Fernandes Lima Suleiman
58

Une bonne façon de faire est d'utiliser app.localsfourni par Express lui-même. Voici la documentation.

// 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;
}
Ali
la source
1
J'ai utilisé cette méthode pour localiser les services http et les remplacer facilement dans les tests unitaires.
Alex
28

Pour déclarer une variable globale, vous devez utiliser un objet global . Comme global.yourVariableName. Mais ce n'est pas un vrai moyen. Pour partager des variables entre les modules, essayez d'utiliser un style d'injection comme

someModule.js:

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

app.js

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

Ou vous pouvez utiliser un objet de substitution pour ce faire. Comme 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');
Vadim Baryshev
la source
7

Voici bien expliquer, en bref:

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

Vous travaillez donc avec un ensemble de modules Node, peut-être un framework comme Express.js, et ressentez soudain le besoin de rendre certaines variables globales. Comment rendre les variables globales dans Node.js?

Le conseil le plus courant pour celui-ci est soit de «déclarer la variable sans le mot clé var», soit «d'ajouter la variable à l'objet global» ou «d'ajouter la variable à l'objet GLOBAL». Lequel utilisez-vous?

Tout d'abord, analysons l'objet global. Ouvrez un terminal, démarrez un Node REPL (invite).

> 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'
Victor Cruz
la source
Dans Express - en utilisant jshint ou linting, en général - cela devient un problème.
Steven Ventimiglia
6

le moyen le plus simple est de déclarer une variable globale dans votre app.js, dès le début:

global.mySpecialVariable = "something"

puis dans tous les itinéraires, vous pouvez l'obtenir:

console.log(mySpecialVariable)
Chaman
la source
1
Dans Express - en utilisant jshint ou linting, en général - cela devient un problème.
Steven Ventimiglia
5

C'était une question utile, mais pourrait l'être davantage en donnant des exemples de code réels. Même l'article lié ne montre pas réellement d'implémentation. Je soumets donc humblement:

Dans votre app.jsdossier, le haut du fichier:

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 n'aura aucune référence à la app.get()méthode. Laissez-les être définis dans les fichiers d'itinéraires individuels.

routes/index.js:

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

et enfin, un fichier de routes réelles, 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
John Gordon
la source
4

Ma méthode préférée est d'utiliser des dépendances circulaires *, que le nœud prend en charge

  • dans app.js définir var app = module.exports = express();comme votre premier ordre du jour
  • Désormais, n'importe quel module requis après coup peut var app = require('./app')y accéder


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


routes / 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');
Will Stern
la source
Bon conseil. Je viens de passer de la méthode require ('./ myroutes') (app) à cela et je me suis cogné la tête contre un mur pendant 10 minutes en essayant de comprendre pourquoi aucun de mes itinéraires ne fonctionnait. N'oubliez pas de retirer les spécifications d'itinéraire dans myroutes.js d'un bloc fonctionnel. Doh!
greg
2

Comme d'autres l'ont déjà partagé, app.set('config', config)c'est génial pour cela. Je voulais simplement ajouter quelque chose que je n'ai pas vu dans les réponses existantes qui est assez important. Une instance Node.js est partagée entre toutes les demandes, donc s'il peut être très pratique de partager une partie configou un routerobjet globalement, le stockage des données d'exécution à l'échelle mondiale sera disponible pour les demandes et les utilisateurs . Considérez cet exemple très simple:

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);

Si vous visitez /baret qu'une autre demande arrive /foo, votre message sera "Welcome to foo!". C'est un exemple idiot, mais il fait passer le message.

Il y a quelques points intéressants à ce sujet à Pourquoi différentes sessions node.js partagent-elles des variables? .

Charlie Schliesser
la source
1

J'ai résolu le même problème, mais j'ai dû écrire plus de code. J'ai créé un server.jsfichier qui utilise express pour enregistrer les itinéraires. Il expose une fonction,, registerqui peut être utilisée par d'autres modules pour enregistrer leurs propres routes. Il expose également une fonction,, startServerpour commencer à écouter un port

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
}

Dans un autre module, utilisez ce fichier pour créer une route.

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
}

Dans le fichier principal, amorcez les deux.

app.js

require('./server').startServer(7000)
require('./web/help').registerHelp()
Amar Dev
la source
1

c'est une chose assez facile, mais les réponses des gens sont à la fois déroutantes et complexes.

laissez-moi vous montrer comment définir une variable globale dans votre expressapplication. Ainsi, vous pouvez y accéder à partir de n'importe quel itinéraire si nécessaire.

Disons que vous voulez définir une variable globale à partir de votre /route principale

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

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

Ainsi, vous obtiendrez req.app de toutes les routes. puis vous devrez utiliser le localspour définir les données globales dans. comme ci-dessus, montrez que vous êtes prêt. maintenant je vais vous montrer comment utiliser ces données

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

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

Comme ci-dessus, la registerroute que vous accédez aux données a été définie plus tôt.

C'est ainsi que vous pouvez faire fonctionner cette chose!

Code Cooker
la source
0

La réponse de John Gordon a été la première des dizaines de réponses à moitié expliquées / documentées que j'ai essayées, à partir de très nombreux sites, qui ont réellement fonctionné. Merci M. Gordon. Désolé, je n'ai pas les points pour cocher votre réponse.

Je voudrais ajouter, pour les autres débutants du partage de fichiers de routage de nœuds, que l'utilisation de la fonction anonyme pour 'index' est ce que l'on verra plus souvent, donc en utilisant l'exemple de John pour le main.js, le fonctionnellement- le code équivalent que l'on trouverait normalement est:

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

J'ai utilisé app.all

La méthode app.all () est utile pour mapper la logique «globale» pour des préfixes de chemin spécifiques ou des correspondances arbitraires.

Dans mon cas, j'utilise confit pour la gestion de la configuration,

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();
    });
});

Dans les itinéraires, vous faites simplement req.app.get('config').get('cookie');

nilesh
la source