全局变量在 app.js 中可以通过路由访问吗?

如何在 app.js中设置一个变量,并使其在所有路由中都可用,至少在位于路由中的 index.js文件中可用。使用 Express 框架和 node.js

185057 次浏览

To make a global variable, just declare it without the var keyword. (Generally speaking this isn't best practice, but in some cases it can be useful - just be careful as it will make the variable available everywhere.)

Here's an example from 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 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');
});


//...

To declare a global variable you need do use global object. Like global.yourVariableName. But it is not a true way. To share variables between modules try to use injection style like

someModule.js:

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

app.js

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

Or you may use surrogate object to do that. Like 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');

This was a helpful question, but could be more so by giving actual code examples. Even the linked article does not actually show an implementation. I, therefore, humbly submit:

In your app.js file, the top of the 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 will not have any reference to app.get() method. Leave these to be defined in the individual routes files.

routes/index.js:

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

and finally, an actual routes file, 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

Here are explain well, in short:

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

So you are working with a set of Node modules, maybe a framework like Express.js, and suddenly feel the need to make some variables global. How do you make variables global in Node.js?

The most common advice to this one is to either "declare the variable without the var keyword" or "add the variable to the global object" or "add the variable to the GLOBAL object". Which one do you use?

First off, let's analyze the global object. Open a terminal, start a Node 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'

John Gordon's answer was the first of dozens of half-explained / documented answers I tried, from many, many sites, that actually worked. Thank You Mr Gordon. Sorry I don't have the points to up-tick your answer.

I would like to add, for other newbies to node-route-file-splitting, that the use of the anonymous function for 'index' is what one will more often see, so using John's example for the main.js, the functionally-equivalent code one would normally find is:

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

It is actually very easy to do this using the "set" and "get" methods available on an express object.

Example as follows, say you have a variable called config with your configuration related stuff that you want to be available in other places:

In app.js:

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


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

In routes/index.js

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

My preferred way is to use circular dependencies*, which node supports

  • in app.js define var app = module.exports = express(); as your first order of business
  • Now any module required after the fact can var app = require('./app') to access it


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

As others have already shared, app.set('config', config) is great for this. I just wanted to add something that I didn't see in existing answers that is quite important. A Node.js instance is shared across all requests, so while it may be very practical to share some config or router object globally, storing runtime data globally will be available across requests and users. Consider this very simple example:

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

If you visit /bar and another request hits /foo, your message will be "Welcome to foo!". This is a silly example, but it gets the point across.

There are some interesting points about this at Why do different node.js sessions share variables?.

A neat way to do this is to use app.locals provided by Express itself. Here is the 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;
}

I used app.all

The app.all() method is useful for mapping “global” logic for specific path prefixes or arbitrary matches.

In my case, I'm using confit for configuration management,

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

In routes, you simply do req.app.get('config').get('cookie');

I solved the same problem, but I had to write more code. I created a server.js file, that uses express to register routes. It exposes a function,register , that can be used by other modules to register their own routes. It also exposes a function, startServer , to start listening to a 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
}

In another module, use this file to create a 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
}

In the main file, bootstrap both.

app.js


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

the easiest way is to declare a global variable in your app.js, early on:

global.mySpecialVariable = "something"

then in any routes you can get it:

console.log(mySpecialVariable)

this is pretty easy thing, but people's answers are confusing and complex at the same time.

let me show you how you can set global variable in your express app. So you can access it from any route as needed.

Let's say you want set a global variable from your main / route

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


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

So you'll get req.app from all the routes. and then you'll have to use the locals to set global data into. like above show you're all set. now I will show you how to use that data

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


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

Like above from register route you're accessing the data has been set earlier.

This is how you can get this thing working!

const app = require('express')();
app.set('globalvar', "xyz");
app.get('globalvar');