【问题标题】:why I am unable to use global objects为什么我无法使用全局对象
【发布时间】:2020-03-08 01:28:19
【问题描述】:

我有一个config 文件:

     const _ = require('lodash');        
     const config = require('./config.json'); 
     const defaultConfig = config.development;
     const environment = process.env.NODE_ENV || 'development';
     const environmentConfig = config[environment]; 
     const finalConfig = _.merge(defaultConfig,environmentConfig);
     global.gConfig = finalConfig; 
     global.lodash = _;

服务器文件:

const express = require('express');
// environment variables
process.env.NODE_ENV = 'development';

const config = require('./config/config.js');

// module variables
const app = express();

app.get('/', (req, res) => {
    res.json(global.lodash.compact([null,1,2,null,"",3]));
});

app.listen(global.gConfig.node_port, () => {
});

当我尝试访问服务器文件中的全局变量时,我需要config.js。没有它,它会显示一个错误。那我们怎么能说它是一个全局变量呢?还有其他方法吗? 我正在使用Node 8.x

【问题讨论】:

  • 我不知道为什么它不起作用,但这是一个糟糕的设计。只需从您的 config.js 文件中导出配置,然后将其require() 导出到您需要的任何地方。这是 node.js 的推荐架构,原因有很多。由于模块被缓存,第二次require() 相同的模块,没有实际的代码运行 - 它只是返回给你以前加载的模块。它安全高效,没有使用全局变量的问题。
  • require('./config/config.js') 将加载config.js,从而执行您在该文件中所做的分配。没有它,没有任何东西被分配给global,值将是undefined。我建议避免使用全局变量 - see my answer below
  • @AndreasPizsa - 你没有看到服务器文件已经有const config = require('./config/config.js'); 吗?他们已经在加载它了。
  • @jfriend00 OP 写道“我需要 config.js。没有它,它会显示错误。那我们怎么能说它是一个全局变量呢?”。似乎 OP 想要更好地了解 globals 和 require 的工作原理。
  • @AndreasPizsa - 嗯,好吧,这不是我理解问题的方式,但我想这可能是他们的意思。有点不清楚的问题,IMO。我以为他们是在说他们写的代码不起作用。

标签: node.js express globals


【解决方案1】:

require 函数做了很多事情。对于初学者,它从所需模块返回module.exports

但它也执行所需模块中的所有代码,就好像整个模块是一个函数一样。

因此,您实际上需要在某处 require 您的 config 文件才能获得以下行:

 global.gConfig = finalConfig; 
 global.lodash = _;

被执行。如果您至少一次不需要config,您的程序将永远不会在global 对象中设置lodashgConfig

不过,现在,一旦你这样做了,你以后可以在任何文件中使用global.lodash,即使该文件不是require config 文件。

因此,基本上,在您要求 config 之后,从 server 要求的任何其他文件都将拥有对 global.lodash 的真正全局访问权限,而无需要求 config 本身。


然而,现在,即使这个答案确实回答了你的问题,我也会彻底考虑 @AndreasPizsa 的答案,因为确实,拥有一个包含大量全局变量的程序通常很难推理。

在您的情况下,您为什么将lodash 设置为global.lodash?你程序中的任何模块都可以自己做const lodash = require('lodash')

还值得一提的是require 确实缓存了所需的模块。第二次需要一个模块时, require 调用不会再次执行代码,它会返回缓存的模块,所以使用多个文件中的require 来检索同一个模块(就像在global 中一样)很漂亮很安全。

【讨论】:

  • 我应该在哪里需要我的配置文件才能访问global.gConfig = finalConfig; global.lodash = _;?在server.js?
  • 在程序开始时,所以你用东西加载global,然后你的任何模块,无论从哪里需要,都可以访问你放入@987654346的东西@.
【解决方案2】:

服务器文件中的 require('./config/config.js') 加载 config.js,从而执行您在该文件中所做的分配。没有它,没有任何东西被分配给global,值将是undefined

更大的上下文

这可能不是您直接寻找的答案,但我认为这是您需要听到的答案,因为在全局变量背后隐藏着更大的问题。

这里的实际挑战是避免全局变量并以在生产中安全使用的方式处理配置。

这两个指针将对此有所帮助:

在环境中存储配置

应用有时会将配置存储为代码中的常量。这违反了十二因素,要求严格分离配置与代码。配置因部署而异,但代码没有。

一个应用程序是否将所有配置正确地从代码中提取出来的试金石是代码库是否可以在任何时候开源,而不会损害任何凭据。

dotenv 安全

dotenv-safe 是一个零依赖模块,它将环境变量从 .env 文件加载到 process.env 中。将配置与代码分开存储在环境中是基于十二要素应用方法。

我希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2019-10-20
    • 2015-03-03
    • 2013-12-30
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 2018-05-22
    相关资源
    最近更新 更多