【发布时间】:2012-04-03 15:30:04
【问题描述】:
我如何在app.js 中设置一个变量并让它在所有路由中可用,至少在位于路由中的index.js 文件中。使用 express 框架和node.js
【问题讨论】:
-
app.locals 对象的属性是应用程序中的局部变量。在您的路由文件中,使用
req.app.locals引用它。
我如何在app.js 中设置一个变量并让它在所有路由中可用,至少在位于路由中的index.js 文件中。使用 express 框架和node.js
【问题讨论】:
req.app.locals 引用它。
使用 express 对象上可用的“set”和“get”方法实际上很容易做到这一点。
示例如下,假设您有一个名为 config 的变量,其中包含您希望在其他地方可用的配置相关内容:
在 app.js 中:
var config = require('./config');
app.configure(function() {
...
app.set('config', config);
...
}
在路由/index.js中
exports.index = function(req, res){
var config = req.app.get('config');
// config is now available
...
}
【讨论】:
req.app.get('name') 就像一个魅力。此属性包含对使用中间件的 Express 应用程序实例的引用。 expressjs.com/pt-br/api.html#req.app
一个巧妙的方法是使用 Express 本身提供的app.locals。
Here 是文档。
// 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;
}
【讨论】:
res.locals 更有用
要创建一个全局变量,只需声明它而不使用var 关键字。 (一般来说,这不是最佳实践,但在某些情况下它可能很有用 - 请小心,因为它会使变量在任何地方都可用。)
这是来自visionmedia/screenshot-app的示例
文件app.js:
/**
* Module dependencies.
*/
var express = require('express')
, stylus = require('stylus')
, redis = require('redis')
, http = require('http');
app = express();
//... require() route files
文件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');
});
//...
【讨论】:
app 关联到哪个范围?
correct one。
要声明一个全局变量,您需要使用global 对象。像 global.yourVariableName。但这不是真正的方法。要在模块之间共享变量,请尝试使用注入样式,例如
someModule.js:
module.exports = function(injectedVariable) {
return {
somePublicMethod: function() {
},
anotherPublicMethod: function() {
},
};
};
app.js
var someModule = require('./someModule')(someSharedVariable);
或者你可以使用代理对象来做到这一点。喜欢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');
【讨论】:
最简单的方法是尽早在 app.js 中声明一个全局变量:
global.mySpecialVariable = "something"
然后在任何路线上你都可以得到它:
console.log(mySpecialVariable)
【讨论】:
这里解释得很好,简而言之:
http://www.hacksparrow.com/global-variables-in-node-js.html
因此,您正在使用一组 Node 模块,可能是像 Express.js 这样的框架,并且突然觉得需要将一些变量设为全局变量。如何在 Node.js 中使变量成为全局变量?
对此最常见的建议是“声明不带 var 关键字的变量”或“将变量添加到全局对象”或“将变量添加到 GLOBAL 对象”。你用的是哪一种?
首先,让我们分析一下全局对象。打开终端,启动 Node REPL(提示)。
> 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'
【讨论】:
这是一个很有帮助的问题,但如果给出实际的代码示例可能会更有用。即使链接的文章实际上也没有显示实现。因此,我谦虚地提交:
在您的app.js 文件中,文件顶部:
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 不会有 any 引用 app.get() 方法。让这些在单独的路由文件中定义。
routes/index.js:
require('./main');
require('./users');
最后,一个实际的路由文件,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
【讨论】:
我的首选方式是使用循环依赖*,节点支持
var app = module.exports = express(); 定义为您的首要任务var app = require('./app') 访问它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
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');
【讨论】:
正如其他人已经分享的那样,app.set('config', config) 非常适合这个。我只是想添加一些我在现有答案中没有看到的非常重要的东西。 Node.js 实例在所有请求之间共享,因此虽然全局共享一些 config 或 router 对象可能非常实用,全局存储运行时数据将跨请求和用户使用。考虑这个非常简单的例子:
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);
如果您访问/bar 并且另一个请求点击/foo,您的消息将是“欢迎来到foo!”。这是一个愚蠢的例子,但它抓住了重点。
Why do different node.js sessions share variables? 有一些有趣的观点。
【讨论】:
这很容易,但人们的答案同时令人困惑和复杂。
让我向您展示如何在您的 express 应用程序中设置全局变量。因此,您可以根据需要从任何路线访问它。
假设你想从你的主路由 / 设置一个全局变量
router.get('/', (req, res, next) => {
req.app.locals.somethingNew = "Hi setting new global var";
});
因此,您将从所有路线中获得 req.app。然后你必须使用locals 来设置全局数据。像上面那样显示你已经准备好了。现在
我将向您展示如何使用这些数据
router.get('/register', (req, res, next) => {
console.log(req.app.locals.somethingNew);
});
像上面从register 访问数据的路由已经设置好了。
这就是你可以让这个东西工作的方法!
【讨论】:
我用app.all
app.all() 方法对于映射特定的“全局”逻辑很有用 路径前缀或任意匹配。
就我而言,我使用confit 进行配置管理,
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();
});
});
在路由中,您只需执行req.app.get('config').get('cookie');
【讨论】:
我解决了同样的问题,但我不得不编写更多代码。
我创建了一个server.js 文件,它使用 express 来注册路由。
它公开了一个函数register,其他模块可以使用该函数来注册自己的路由。
它还公开了一个函数 startServer 来开始监听端口
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
}
在另一个模块中,使用此文件创建路由。
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
}
在主文件中,引导两者。
app.js
require('./server').startServer(7000)
require('./web/help').registerHelp()
【讨论】:
John Gordon 的答案是我在许多网站上尝试过的几十个半解释/记录的答案中的第一个,这些答案确实有效。谢谢戈登先生。抱歉,我没有足够的分数来支持你的答案。
我想补充一点,对于 node-route-file-splitting 的其他新手来说,使用匿名函数来实现 'index' 是人们经常看到的,所以使用 John 的 main.js 示例,通常会找到的功能等效代码是:
app.get('/',(req, res) {
res.render('index', { title: 'Express' });
});
【讨论】: