繁体   English   中英

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

[英]Global Variable in app.js accessible in routes?

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

使用 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
  ...
}

要创建一个全局变量,只需在没有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');
});

//...

一个巧妙的方法是使用 Express 本身提供的app.locals 是文档。

// 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;
}

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

someModule.js:

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

应用程序.js

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

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

someModule.js:

var hub = require('hub');

module.somePublicMethod = function() {
    // We can use hub.db here
};

module.anotherPublicMethod = function() {
};

应用程序.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 关键字”或“将变量添加到全局对象”或“将变量添加到全局对象”。 你用哪一种?

首先,让我们分析一下全局对象。 打开终端,启动 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 不会有任何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

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

  • 在 app.js 中定义var app = module.exports = express(); 作为您的第一笔生意
  • 现在任何事后需要的模块都可以var app = require('./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');

正如其他人已经分享的那样, 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 ,您的消息将是“欢迎使用 foo!”。 这是一个愚蠢的例子,但它明白了这一点。

为什么不同的 node.js 会话共享变量? .

这是很容易的事情,但人们的答案同时令人困惑和复杂。

让我向您展示如何在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路由中的数据已经设置得更早。

这就是你可以让这个东西工作的方法!

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

我使用了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()

约翰戈登的答案是我尝试过的许多解释/记录在案的答案中的第一个,这些答案来自许多许多网站,但确实有效。 谢谢戈登先生。 抱歉,我没有足够的分数来为您的答案打勾。

我想补充一点,对于节点路由文件拆分的其他新手,将匿名函数用于“索引”是人们更经常看到的,因此使用约翰的 main.js 示例,功能上-通常会找到的等效代码是:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM