Variable global en app.js accesible en rutas?

91

¿Cómo configuro una variable app.jsy la tengo disponible en todas las rutas, al menos en el index.jsarchivo ubicado en las rutas? utilizando el marco express ynode.js

Technupe
fuente
1
El objeto app.locals tiene propiedades que son variables locales dentro de la aplicación. En su archivo de ruta, haga referencia a él con req.app.locals.
Ronnie Royston

Respuestas:

65

Para hacer una variable global, simplemente declare sin la varpalabra clave. (En términos generales, esta no es la mejor práctica, pero en algunos casos puede ser útil; solo tenga cuidado, ya que hará que la variable esté disponible en todas partes).

Aquí hay un ejemplo de visionmedia / screenshot-app

archivo app.js :

/**
 * Module dependencies.
 */

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

app = express();

//... require() route files

rutas de archivo / 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
fuente
6
Como nota, generalmente es mejor ser explícito acerca de pasar variables e instanciarlas, para que no anule accidentalmente la referencia en otro lugar de la aplicación, o lo que sea.
Paul
3
Esta es realmente mala forma, como señaló Paul. Sugeriría el patrón de inyección mencionado a continuación. Sí, más código de placa de caldera para que no se vea "bonito" pero garantiza que su código sea modular ... algo que le gustará si este no es su último proyecto;)
srquinn
Depende de las circunstancias en mi humilde opinión. Sí, las vars globales generalmente no son una buena práctica (como dije en mi respuesta) y, al comenzar desde cero, diría que organice todo en módulos separados. Pero si se está integrando con código existente, a menudo hay otras consideraciones: esta es una solución (fácil, pero peligrosa).
Jesse Fulton
2
¿Alguien podría explicar por qué esto funciona en referencia a la semántica de Javascript? ¿A qué alcance appse asocia?
Ali
No creo que esta respuesta deba marcar como correctuna.
Code Cooker
93

En realidad, es muy fácil hacer esto usando los métodos "set" y "get" disponibles en un objeto express.

Ejemplo de la siguiente manera, digamos que tiene una variable llamada config con las cosas relacionadas con su configuración que desea que estén disponibles en otros lugares:

En app.js:

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

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

En rutas / index.js

exports.index = function(req, res){
  var config = req.app.get('config');
  // config is now available
  ...
}
Mandy
fuente
¿Establecer 'aplicación' global? Si. Pero este método es el mejor para salvarnos de los problemas y el caos.
diproart
53
para los que llegan tarde: app.configure se elimina en Express 4.x
zamil
Agradable, req.app.get('name')funciona a las mil maravillas. Esta propiedad contiene una referencia a la instancia de la aplicación Express que usa el middleware. expressjs.com/pt-br/api.html#req.app
Lazaro Fernandes Lima Suleiman
57

Una forma ordenada de hacer esto es utilizando el app.localspropio Express. Aquí está la documentación.

// 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
fuente
1
Usé este método para ubicar servicios http y anular fácilmente en pruebas unitarias.
Alex
28

Para declarar una variable global, debe utilizar un objeto global . Como global.yourVariableName. Pero no es una verdadera forma. Para compartir variables entre módulos, intente usar un estilo de inyección como

someModule.js:

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

app.js

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

O puede usar un objeto sustituto para hacer eso. Como 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
fuente
7

A continuación se explican bien, en resumen:

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

Entonces, está trabajando con un conjunto de módulos de nodo, tal vez un marco como Express.js, y de repente siente la necesidad de hacer que algunas variables sean globales. ¿Cómo se hacen las variables globales en Node.js?

El consejo más común para este es "declarar la variable sin la palabra clave var" o "agregar la variable al objeto global" o "agregar la variable al objeto GLOBAL". Cual usas?

En primer lugar, analicemos el objeto global. Abra una terminal, inicie un REPL de nodo (indicador).

> 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'
Víctor Cruz
fuente
En Express, cuando se usa jshint o linting, en general, esto se convierte en un problema.
Steven Ventimiglia
6

la forma más fácil es declarar una variable global en su app.js, desde el principio:

global.mySpecialVariable = "something"

entonces en cualquier ruta puedes conseguirlo:

console.log(mySpecialVariable)
Chamán
fuente
1
En Express, cuando se usa jshint o linting, en general, esto se convierte en un problema.
Steven Ventimiglia
5

Esta fue una pregunta útil, pero podría ser más importante si proporciona ejemplos de código reales. Incluso el artículo vinculado no muestra realmente una implementación. Por tanto, humildemente me someto:

En su app.jsarchivo, la parte superior del archivo:

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 no tendrá ninguna referencia al app.get()método. Deje que se definan en los archivos de rutas individuales.

routes/index.js:

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

y, por último, un archivo de rutas reales, 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
fuente
4

Mi forma preferida es usar dependencias circulares *, que el nodo admite

  • en app.js define var app = module.exports = express();como su primera orden del día
  • Ahora cualquier módulo requerido después del hecho puede var app = require('./app')acceder a él.


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


rutas / 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
fuente
Buen consejo. Acabo de pasar del método require ('./ myroutes') (app) a hacer esto y golpeé mi cabeza contra una pared durante 10 minutos tratando de averiguar por qué ninguna de mis rutas funcionó. No olvide sacar las especificaciones de ruta en myroutes.js de un bloque de funciones. Doh!
Greg
2

Como otros ya han compartido, app.set('config', config)es genial para esto. Solo quería agregar algo que no vi en las respuestas existentes que es bastante importante. Una instancia de Node.js se comparte en todas las solicitudes, por lo que, si bien puede ser muy práctico compartir algunos configu routerobjetos de forma global, el almacenamiento de datos en tiempo de ejecución de forma global estará disponible para todas las solicitudes y usuarios . Considere este ejemplo muy 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 visita /bary recibe otra solicitud /foo, su mensaje será "¡Bienvenido a foo!". Este es un ejemplo tonto, pero transmite el mensaje.

Hay algunos puntos interesantes sobre esto en ¿Por qué las diferentes sesiones de node.js comparten variables? .

Charlie Schliesser
fuente
1

Resolví el mismo problema, pero tuve que escribir más código. Creé un server.jsarchivo, que usa express para registrar rutas. Expone una función, registerque puede ser utilizada por otros módulos para registrar sus propias rutas. También expone una función startServer, para empezar a escuchar un puerto

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
}

En otro módulo, use este archivo para crear una ruta.

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
}

En el archivo principal, arranque ambos.

app.js

require('./server').startServer(7000)
require('./web/help').registerHelp()
Amar Dev
fuente
0

La respuesta de John Gordon fue la primera de docenas de respuestas a medio explicar / documentadas que probé, en muchos, muchos sitios, que realmente funcionaron. Gracias, señor Gordon. Lo siento, no tengo los puntos para mejorar tu respuesta.

Me gustaría agregar, para otros novatos en node-route-file-splitting, que el uso de la función anónima para 'índice' es lo que uno verá más a menudo, por lo que usando el ejemplo de John para main.js, el funcionalmente- el código equivalente que uno encontraría normalmente es:

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

Solía app.all

El método app.all () es útil para mapear la lógica "global" para prefijos de ruta específicos o coincidencias arbitrarias.

En mi caso, estoy usando confit para la gestión de la configuración,

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

En rutas, simplemente haces req.app.get('config').get('cookie');

nilesh
fuente
0

esto es bastante fácil, pero las respuestas de las personas son confusas y complejas al mismo tiempo.

déjame mostrarte cómo puedes establecer una variable global en tu expressaplicación. Para que pueda acceder a él desde cualquier ruta según sea necesario.

Digamos que desea establecer una variable global de su /ruta principal

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

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

Entonces obtendrás req.app de todas las rutas. y luego tendrá que usar localspara establecer datos globales en. como arriba muestra que estás listo. ahora te mostraré cómo usar esos datos

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

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

Como arriba, desde la registerruta a la que está accediendo, los datos se establecieron anteriormente.

¡Así es como puedes hacer que esto funcione!

Cocina de código
fuente