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


91

如何在变量中设置变量app.js并使变量在所有路由中可用,至少在路由中的index.js文件中可用。使用快速框架和node.js


1
app.locals对象具有的应用程序中的局部变量的性质。在您的路线文件中,使用引用req.app.locals
罗尼·罗伊斯顿

Answers:


65

要创建全局变量,只需声明不带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

文件路由/ 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
需要注意的是,通常最好明确传递变量并将其实例化,这样您就不会在应用程序的其他位置或您拥有的内容中意外删除ref。
保罗

3
正如Paul所指出的,这确实是一种糟糕的形式。我建议以下提到的注入方式。是的,更多样板代码,因此看起来不“漂亮”,但是可以确保您的代码是模块化的……如果这不是您的最后一个项目,您会喜欢的东西;)
srquinn

这取决于恕我直言的情况。是的,全局变量通常不是一个好习惯(正如我在回答中所述),当从头开始时,我会说将所有内容组织到单独的模块中。但是,如果要与现有代码集成,则通常还有其他注意事项-这恰好是一个(简单但又危险的)解决方案。
杰西·富尔顿

2
有人可以解释为什么这可以参考Javascript的语义吗?与哪个范围app相关联?
阿里

我认为这个答案不应标记为correct一个。
Code Cooker

91

使用快速对象上可用的“设置”和“获取”方法实际上很容易做到这一点。

如下例所示,假设您有一个名为config的变量,其中包含与配置相关的内容,并且希望在其他地方使用:

在app.js中:

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

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

在routes / index.js中

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

全局设置“应用”?是。但是这种方法最适合使我们免于遇到问题和混乱。
diproart 2014年

53
对于后来者:app.configure在express 4.x中删除
zamil

不错,req.app.get('name')就像魅力一样。此属性保存对使用中间件的Express应用程序实例的引用。expressjs.com/pt-br/api.html#req.app
Lazaro Fernandes Lima Suleiman

57

进行此操作的一种好方法是使用app.localsExpress本身提供的功能。 是文档。

// 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
我使用这种方法来定位http服务,并在单元测试中轻松覆盖。
亚历克斯(Alex)

28

要声明全局变量,您需要使用全局对象。像global.yourVariableName。但这不是真正的方法。要在模块之间共享变量,请尝试使用注入样式,例如

someModule.js:

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

app.js

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

或者您可以使用代理对象来做到这一点。像集线器

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

简而言之,这里有很好的解释:

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

因此,您正在使用一组Node模块(例如Express.js之类的框架)工作,突然感到需要全局设置一些变量。如何在Node.js中使变量成为全局变量?

最常见的建议是“声明不带var关键字的变量”或“将变量添加到全局对象”或“将变量添加到GLOBAL对象”。您使用哪一个?

首先,让我们分析全局对象。打开终端,启动节点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'

在Express中-通常使用jshint或linting时-这将成为问题。
史蒂文·文蒂米利亚

6

最简单的方法是尽早在app.js中声明一个全局变量:

global.mySpecialVariable = "something"

然后在任何路线上您都可以得到它:

console.log(mySpecialVariable)

1
在Express中-通常使用jshint或linting时-这将成为问题。
史蒂文·文蒂米利亚

5

这是一个有用的问题,但通过给出实际的代码示例,可能会更有用。甚至链接的文章实际上也没有显示实现。因此,我谦卑地提交:

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将没有对方法的任何引用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

4

我的首选方式是使用循环依赖关系*,该节点支持

  • 在app.js中定义var app = module.exports = express();为您的第一笔业务
  • 现在事实之后需要的任何模块都var app = require('./app')可以访问它


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


路线/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');

大提示。我只是从require('./ myroutes')(app)方法转到执行此操作,然后将我的头撞在墙上10分钟,试图弄清为什么我的路线都不起作用。不要忘记从功能块中取出myroutes.js中的路由规范。h!
greg

2

正如其他人已经分享的那样,app.set('config', config)这非常有用。我只是想添加一些在现有答案中没有看到的非常重要的内容。Node.js实例在所有请求之间共享,因此虽然在全局范围内共享某些对象configrouter对象可能非常实用,但在请求和用户之间可以全局存储运行时数据。考虑这个非常简单的示例:

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,您的消息将是“ Welcome to foo!”。这是一个愚蠢的例子,但可以理解这一点。

为什么不同的node.js会话共享变量,对此有一些有趣的观点


1

我解决了同样的问题,但是我不得不写更多的代码。我创建了一个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()

0

约翰·高登(John Gordon)的答案是我在许多站点上尝试的数十种未解释的/有文档记录的答案中的第一个,该答案实际上是有效的。谢谢戈登先生。抱歉,我没有要补充您的答案的要点。

对于其他新手,我想在node-route-file-splitting中添加匿名函数用于“索引”,这将是人们经常看到的,因此使用John的main.js示例,该函数通常可以找到的等效代码是:

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

0

我用了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');


0

这是一件很容易的事,但是人们的答案却是混乱而又复杂的。

让我向您展示如何在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路线一样,您正在访问的数据已被更早设置。

这是使此事情起作用的方法!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.