简体   繁体   English

在 Node.js 中的文件之间共享变量?

[英]Share variables between files in Node.js?

Here are 2 files:这里有2个文件:

// main.js
require('./module');
console.log(name); // prints "foobar"

// module.js
name = "foobar";

When I don't have "var" it works.当我没有“var”时,它可以工作。 But when I have:但是当我有:

// module.js
var name = "foobar";

name will be undefined in main.js.名称将在 main.js 中未定义。

I have heard that global variables are bad and you better use "var" before the references.我听说全局变量不好,你最好在引用之前使用“var”。 But is this a case where global variables are good?但这是全局变量好的情况吗?

Global variables are almost never a good thing (maybe an exception or two out there...).全局变量几乎从来都不是一件好事(可能有一两个例外......)。 In this case, it looks like you really just want to export your "name" variable.在这种情况下,您似乎真的只想导出您的“名称”变量。 Eg,例如,

// module.js
var name = "foobar";
// export it
exports.name = name;

Then, in main.js...然后,在 main.js...

//main.js
// get a reference to your required module
var myModule = require('./module');

// name is a member of myModule due to the export above
var name = myModule.name;

I'm unable to find an scenario where a global var is the best option, of course you can have one, but take a look at these examples and you may find a better way to accomplish the same:我找不到全局var是最佳选择的场景,当然你可以有一个,但看看这些例子,你可能会找到更好的方法来完成同样的事情:

Scenario 1: Put the stuff in config files场景1:把东西放在配置文件中

You need some value that it's the same across the application, but it changes depending on the environment (production, dev or test), the mailer type as example, you'd need:您需要一些在整个应用程序中相同的值,但它会根据环境(生产、开发或测试)而变化,例如邮件类型,您需要:

// File: config/environments/production.json
{
    "mailerType": "SMTP",
    "mailerConfig": {
      "service": "Gmail",
      ....
}

and

// File: config/environments/test.json
{
    "mailerType": "Stub",
    "mailerConfig": {
      "error": false
    }
}

(make a similar config for dev too) (也为 dev 做一个类似的配置)

To decide which config will be loaded make a main config file (this will be used all over the application)要决定将加载哪个配置,请制作一个主配置文件(这将在整个应用程序中使用)

// File: config/config.js
var _ = require('underscore');

module.exports = _.extend(
    require(__dirname + '/../config/environments/' + process.env.NODE_ENV + '.json') || {});

And now you can get the data like this:现在你可以得到这样的数据

// File: server.js
...
var config = require('./config/config');
...
mailer.setTransport(nodemailer.createTransport(config.mailerType, config.mailerConfig));

Scenario 2: Use a constants file场景 2:使用常量文件

// File: constants.js
module.exports = {
  appName: 'My neat app',
  currentAPIVersion: 3
};

And use it this way并以这种方式使用它

// File: config/routes.js

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

module.exports = function(app, passport, auth) {
  var apiroot = '/api/v' + constants.currentAPIVersion;
...
  app.post(apiroot + '/users', users.create);
...

Scenario 3: Use a helper function to get/set the data场景 3:使用辅助函数获取/设置数据

Not a big fan of this one, but at least you can track the use of the 'name' (citing the OP's example) and put validations in place.不是这个的忠实粉丝,但至少您可以跟踪“名称”的使用(引用 OP 的示例)并进行验证。

// File: helpers/nameHelper.js

var _name = 'I shall not be null'

exports.getName = function() {
  return _name;
};

exports.setName = function(name) {
  //validate the name...
  _name = name;
};

And use it并使用它

// File: controllers/users.js

var nameHelper = require('../helpers/nameHelper.js');

exports.create = function(req, res, next) {
  var user = new User();
  user.name = req.body.name || nameHelper.getName();
  ...

There could be a use case when there is no other solution than having a global var , but usually you can share the data in your app using one of these scenarios, if you are starting to use node.js (as I was sometime ago) try to organize the way you handle the data over there because it can get messy really quick.可能有一个用例,除了拥有全局var之外没有其他解决方案,但如果您开始使用 node.js(就像我前一段时间一样),通常您可以使用这些场景之一在您的应用程序中共享数据尝试组织你在那里处理数据的方式,因为它很快就会变得混乱。

If we need to share multiple variables use the below format如果我们需要共享多个变量,请使用以下格式

//module.js
   let name='foobar';
   let city='xyz';
   let company='companyName';

   module.exports={
    name,
    city,
    company
  }

Usage用法

  // main.js
    require('./modules');
    console.log(name); // print 'foobar'

Save any variable that want to be shared as one object.将任何想要共享的变量保存为一个对象。 Then pass it to loaded module so it could access the variable through object reference..然后将其传递给加载的模块,以便它可以通过对象引用访问变量..

// main.js
var myModule = require('./module.js');
var shares = {value:123};

// Initialize module and pass the shareable object
myModule.init(shares);

// The value was changed from init2 on the other file
console.log(shares.value); // 789

On the other file..在另一个文件..

// module.js
var shared = null;

function init2(){
    console.log(shared.value); // 123
    shared.value = 789;
}

module.exports = {
    init:function(obj){
        // Save the shared object on current module
        shared = obj;

        // Call something outside
        init2();
    }
}

Not a new approach but a bit optimized.不是一种新方法,但有点优化。 Create a file with global variables and share them by export and require .创建一个包含全局变量的文件,并通过exportrequire共享它们。 In this example, Getter and Setter are more dynamic and global variables can be readonly.在此示例中,Getter 和 Setter 更具动态性,全局变量可以是只读的。 To define more globals, just add them to globals object.要定义更多全局变量,只需将它们添加到globals对象。

global.js global.js

const globals = {
  myGlobal: {
    value: 'can be anytype: String, Array, Object, ...'
  },
  aReadonlyGlobal: {
    value: 'this value is readonly',
    protected: true
  },
  dbConnection: {
    value: 'mongoClient.db("database")'
  },
  myHelperFunction: {
    value: function() { console.log('do help') }
  },
}

exports.get = function(global) {
  // return variable or false if not exists
  return globals[global] && globals[global].value ? globals[global].value : false;
};

exports.set = function(global, value) {
  // exists and is protected: return false
  if (globals[global] && globals[global].protected && globals[global].protected === true)
    return false;
  // set global and return true
  globals[global] = { value: value };
  return true;
};

examples to get and set in any-other-file.js在 any-other-file.js 中获取和设置的示例

const globals = require('./globals');

console.log(globals.get('myGlobal'));
// output: can be anytype: String, Array, Object, ...

globals.get('myHelperFunction')();
// output: do help

let myHelperFunction = globals.get('myHelperFunction');
myHelperFunction();
// output: do help

console.log(globals.set('myGlobal', 'my new value'));
// output: true
console.log(globals.get('myGlobal'));
// output: my new value

console.log(globals.set('aReadonlyGlobal', 'this shall not work'));
// output: false
console.log(globals.get('aReadonlyGlobal'));
// output: this value is readonly

console.log(globals.get('notExistingGlobal'));
// output: false

a variable declared with or without the var keyword got attached to the global object.使用或不使用 var 关键字声明的变量附加到全局对象。 This is the basis for creating global variables in Node by declaring variables without the var keyword.这是在 Node 中通过声明不带 var 关键字的变量来创建全局变量的基础。 While variables declared with the var keyword remain local to a module.而使用 var 关键字声明的变量仍然是模块的本地变量。

see this article for further understanding - https://www.hacksparrow.com/global-variables-in-node-js.html请参阅本文以进一步了解 - https://www.hacksparrow.com/global-variables-in-node-js.html

With a different opinion, I think the global variables might be the best choice if you are going to publish your code to npm , cuz you cannot be sure that all packages are using the same release of your code.有不同的意见,我认为如果您要将代码发布到npmglobal变量可能是最佳选择,因为您不能确定所有包都使用相同版本的代码。 So if you use a file for exporting a singleton object, it will cause issues here.因此,如果您使用文件来导出singleton对象,则会在此处引起问题。

You can choose global , require.main or any other objects which are shared across files.您可以选择globalrequire.main或任何其他跨文件共享的对象。

Otherwise, install your package as an optional dependency package can avoid this problem.否则,将您的包安装为可选的依赖包可以避免此问题。

Please tell me if there are some better solutions.请告诉我是否有更好的解决方案。

If the target is the browser (by bundling Node code via Parcel.js or similar), you can simply set properties on the window object, and they become global variables:如果目标是浏览器(通过 Parcel.js 或类似的方式捆绑 Node 代码),您只需在window object 上设置属性,它们就会成为全局变量:

window.variableToMakeGlobal = value;

Then you can access this variable from all modules (and more generally, from any Javascript context).然后,您可以从所有模块(更一般地说,从任何 Javascript 上下文)访问此变量。

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

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