node.js模块导出如何在所有模块之间使用数据?

时间:2018-10-21 00:24:28

标签: node.js node-modules

我想在所有节点模块之间使用更新的(并且只有那时)全局变量。怎么做?问题在代码中。

app.js

var data = 'data';

var global = require('glob.js')(data);
// here we are require your globals variables and we corectly 'set them'

console.log(globals.glob1);
// we can use them here

glob.js

module.exports  = function(data)
{
    var globs = {
        glob1 : data.toLowerCase(),
        glob2 : data.toUpperCase()
    }
    return globs;
}

mod.js

var global = require('glob.js'); // I require globals but they are not set...

function funct(someOtherData, someMoreData)
{
    var test = global.glob1;
    console.log(test);
    // why I can't use globals here ? How can I use corectly set globals (globals need to be updated first - app.js, then ALL other modules should be able to use correctly set globals)?
}

module.export = funct;

3 个答案:

答案 0 :(得分:0)

有2个选项:

  1. 使用nodejs global变量(不推荐)
  2. 创建共享模块

您选择了第二个选项,但是通过导出函数做了一些错误的选择。导入包并调用函数时,它始终会创建新的 globs 对象,并使用您的 data 来实现它。相反,您可以导出对象。简单的例子

glob.js
全局对象在这里定义

module.exports = {
  glob1: '1',
  glob2: '2'
};

mod.js
您可以在此处更改全局对象,例如

var globs = require('./glob');

module.exports.updateGlob1 = function(data) {
  globs.glob1 = data;
};

app.js
在这里,如果您访问全局变量,则可以看到它已更新

var globs = require('./glob');
var mod = require('./mod');

mod.updateGlob1('1 plus 2');
console.log(globs.glob1); // Output: '1 plus 2'

可能会有更复杂的示例,因为通常使用IIFE作为模块设计模式。

更新

另一个使用IIFE的示例。

glob.js

module.exports = (function() {
  var glob1 = 'initial value';

  return {
    // Getter method
    getGlob1() {
      return glob1;
    },

    // Setter method
    setGlob1(value) {
      glob1 = value;
    }
  }
})();

mod.js

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

module.exports.testFn = function() {
  // Access global variable with getter method
  console.log('In mod.js', shared.getGlob1());
};

app.js

var shared = require('./shared');
var mod = require('./mod');

// Print initial value
console.log('Initial', shared.getGlob1());

// Set new value to global variable
shared.setGlob1('new value');

// Print updated value
console.log('In app.js', shared.getGlob1());

// Use global variable in mod.js file
mod.testFn();

答案 1 :(得分:0)

您可以使用global.变量标识符在NodeJS中设置全局变量,而不是var,例如:

app.js

var data = 'data';

var glob = require('./glob.js');
glob(data);
// here we are require your globals variables and we corectly 'set them'

console.log(global.gl.glob1);
var mod = require('./mod.js');
mod();
// we can use them here 

glob.js

module.exports  = function(data)
{
    console.log("setting globals");
    global.gl = {
        glob1 : '1' + data,
        glob2 : '2' + data
    }
    // return global.gl; // can be removed 
}

mod.js

function funct(someOtherData, someMoreData)
{
    var test = global.gl.glob1;
    console.log(test);
    test = global.gl.glob2;
    console.log(test);
    // why I can't use globals here ? How can I use corectly set globals (globals need to be updated first - app.js, then ALL other modules should be able to use correctly set globals)?
}

module.exports = funct;

正如您在 glob.js 中看到的那样,我将var globs =切换为global.gl =,然后在 mod.js 中将其用作{ {1}}。

运行 app.js 输出:

global.gl

答案 2 :(得分:0)

要获得答案,请滚动至下面的 TLDR 部分,但请继续阅读以了解原因。

Part1-函数与函数调用之间的区别

您的第一个错误是您要导出函数,而不是对象:

module.exports  = function(data) // <---- this is a function
{
    var globs = {
        glob1 : data.toLowerCase(),
        glob2 : data.toUpperCase()
    }
    return globs;
}

,然后在 app.js 中执行以下操作:

console.log(globs.glob1); <--- globs is a function, not an object

何时应该执行此操作:

console.log(globs().glob1);

这是为什么?好的,让您暂时忘记您的模块。考虑以下代码:

var a = function(){ return 2 };

console.log(a);   // do you expect this to print a function or 2?
console.log(a()); // what do you expect this to print?

这是关于所有编程语言中函数的非常基本的规则,而不仅仅是javascript:要获取返回值,您需要调用函数。因此,在您的代码中:

function myExportedFunction (data) {
    // some logic here...
    return globs;
}

console.log(myExportedFunction);         // prints a function
console.log(myExportedFunction());       // prints the globs object
console.log(myExportedFunction().glob1); // prints value of glob1

真的很简单。没有魔术语法。您只是忘记了返回glob对象,而是使用了函数指针。显然,该函数没有glob1属性,因此未定义它是正确的。

Part2-函数局部变量

好。假设您进行了我上面建议的更改。函数的编写方式存在一个明显的问题。当您这样做时会发生什么:

var glob = require('glob.js')();
console.log(glob.glob1); // <--- prints "undefined"

因此,第一个问题是您不检查是否要传递数据或什么都不传递。因此,每次调用该函数时,都会覆盖存储的值。

还有另一个问题,每次调用该函数时,总是返回一个不同的对象。让我们看看返回时局部变量是如何工作的:

function a () {
    var data = {}
    return data;
}

var x = a();
var y = a();

x.testing = 1;
y.testing = 2;

console.log(x.testing); // prints 1
console.log(y.testing); // prints 2

因此,每次调用创建局部变量的函数时,您将返回一个不同的对象。实际上,这实际上不是变量,而是对象文字语法:

var a = {};
// is basically the same as
var a = new Object();

如果将上面的示例更改为:

function a () {
    return {};
}

它的行为仍然相同。

TLDR

那么,我们该如何解决?很简单,在函数外创建对象,然后检查是否通过data进行初始化:

var globs = {
    glob1 : "",
    glob2 : ""
}

module.exports  = function(data)
{
    globs.glob1 = data.toLowerCase();
    globs.glob2 = data.toUpperCase();

    return globs;
}

现在一切正常:

app.js

var global = require('glob.js')(data);

mod.js

var global = require('glob.js')();

Epologue-模块为单例

对您来说,上面的方法为什么起作用也许不明显。如果您已经知道为什么我要写这篇文章作为将来读者的参考。

在node.js中,模块被实现为适当的单例。因此,在节点中,如果您想要单例,则只需编写一个模块,就无需为其实现任何特殊的代码。

这意味着所有模块全局变量(模块作用域变量)在所有需求之间共享。这是一个非常简单的模块,可以在所有模块之间共享一个变量:

shared.js

var x = "";

module.exports = {
    set: function (val) {x=val},
    get: function () {return x}
}

a.js

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

shared.set("hello world");

b.js

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

console.log(shared.get()); // prints "hello world"

我们正在使用此功能在上面的代码中声明一个共享的glob变量。