简体   繁体   English

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

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

How do i set a variable in app.js and have it be available in all the routes, atleast in the index.js file located in routes.我如何在app.js中设置变量并使其在所有路由中可用,至少在位于路由中的index.js文件中可用。 using the express framework and node.js使用 express 框架和node.js

It is actually very easy to do this using the "set" and "get" methods available on an express object.使用 express 对象上可用的“set”和“get”方法实际上很容易做到这一点。

Example as follows, say you have a variable called config with your configuration related stuff that you want to be available in other places:示例如下,假设您有一个名为 config 的变量,其中包含您希望在其他地方可用的配置相关内容:

In app.js:在 app.js 中:

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

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

In routes/index.js在路由/index.js

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

To make a global variable, just declare it without the var keyword.要创建一个全局变量,只需在没有var关键字的情况下声明它。 (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这是来自visionmedia/screenshot-app的示例

file app.js :文件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文件路由/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');
});

//...

A neat way to do this is to use app.locals provided by Express itself.一个巧妙的方法是使用 Express 本身提供的app.locals 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;
}

To declare a global variable you need do use global object.要声明一个全局变量,您需要使用全局对象。 Like global.yourVariableName.像 global.yourVariableName。 But it is not a true way.但这不是真正的方法。 To share variables between modules try to use injection style like要在模块之间共享变量,请尝试使用注入样式,例如

someModule.js: someModule.js:

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

app.js应用程序.js

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

Or you may use surrogate object to do that.或者您可以使用代理对象来做到这一点。 Like hub .集线器

someModule.js: someModule.js:

var hub = require('hub');

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

module.anotherPublicMethod = function() {
};

app.js应用程序.js

var hub = require('hub');
hub.db = dbConnection;
var someModule = require('./someModule');

the easiest way is to declare a global variable in your app.js, early on:最简单的方法是尽早在 app.js 中声明一个全局变量:

global.mySpecialVariable = "something"

then in any routes you can get it:然后在任何路线中你都可以得到它:

console.log(mySpecialVariable)

Here are explain well, in short:这里有很好的解释,简而言之:

http://www.hacksparrow.com/global-variables-in-node-js.html 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.所以你正在使用一组 Node 模块,可能是一个像 Express.js 这样的框架,突然觉得需要让一些变量成为全局变量。 How do you make variables global in Node.js?你如何在 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".对此最常见的建议是“声明变量而不使用 var 关键字”或“将变量添加到全局对象”或“将变量添加到全局对象”。 Which one do you use?你用哪一种?

First off, let's analyze the global object.首先,让我们分析一下全局对象。 Open a terminal, start a Node REPL (prompt).打开终端,启动 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'

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: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 will not have any reference to app.get() method. app.js 不会有任何app.get()方法的引用。 Leave these to be defined in the individual routes files.将这些保留在各个路由文件中定义。

routes/index.js : routes/index.js

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

and finally, an actual routes file, routes/main.js :最后,一个实际的路由文件, 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

My preferred way is to use circular dependencies*, which node supports我的首选方法是使用循环依赖*,该节点支持

  • in app.js define var app = module.exports = express();在 app.js 中定义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现在任何事后需要的模块都可以var app = require('./app')来访问它


app.js 应用程序.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 路线/ 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.正如其他人已经分享的那样, app.set('config', config)非常适合这个。 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 . Node.js 实例在所有请求之间共享,因此虽然全局共享一些configrouter对象可能非常实用,但全局存储运行时数据将在请求和用户之间可用 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!".如果您访问/bar并且另一个请求命中/foo ,您的消息将是“欢迎使用 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? 为什么不同的 node.js 会话共享变量? . .

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.让我向您展示如何在express应用程序中设置全局变量。 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.所以你会从所有的路由中得到 req.app。 and then you'll have to use the locals to set global data into.然后你必须使用locals来设置全局数据。 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.像上面一样,您正在访问的register路由中的数据已经设置得更早。

This is how you can get this thing working!这就是你可以让这个东西工作的方法!

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

I used app.all我使用了app.all

The app.all() method is useful for mapping “global” logic for specific path prefixes or arbitrary matches. app.all() 方法可用于为特定路径前缀或任意匹配映射“全局”逻辑。

In my case, I'm using confit for configuration management,就我而言,我使用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();
    });
});

In routes, you simply do req.app.get('config').get('cookie');在路由中,您只需执行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.我创建了一个server.js文件,它使用 express 来注册路由。 It exposes a function, register , that can be used by other modules to register their own routes.它公开了一个函数register ,其他模块可以使用它来注册自己的路由。 It also exposes a function, startServer , to start listening to a port它还公开了一个函数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
}

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

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:我想补充一点,对于节点路由文件拆分的其他新手,将匿名函数用于“索引”是人们更经常看到的,因此使用约翰的 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