According to this post we know that variables can be exported from one module in JavaScript:
// module.js
(function(handler) {
var MSG = {};
handler.init = init;
handler.MSG = MSG;
function init() {
// do initialization on MSG here
MSG = ...
}
})(module.exports);
// app.js
require('controller');
require('module').init();
// controller.js
net = require('module');
console.log(net.MSG); // output: empty object {}
Those above codes are in Node.js and I get one empty object in my controller.js. Could you please help me figure out the reason of this?
Update1
I have updated the above codes:
// module.js
(function(handler) {
// MSG is local global variable, it can be used other functions
var MSG = {};
handler.init = init;
handler.MSG = MSG;
function init(config) {
// do initialization on MSG through config here
MSG = new NEWOBJ(config);
console.log('init is invoking...');
}
})(module.exports);
// app.js
require('./module').init();
require('./controller');
// controller.js
net = require('./module');
net.init();
console.log(net.MSG); // output: still empty object {}
Output: still empty object. Why?
When you console.log(net.MSG) in controller.js, you have not yet called init(). That only comes later in app.js.
If you init() in controller.js it should work.
Another issue i discovered through testing.
When you do MSG = {t: 12}; in init(), you overwrite MSG with a new object, but that doesn't affect handler.MSG's reference. You need to either set handler.MSG directly, or modify MSG: MSG.t = 12;.
Related
I am trying to declare an array from the function globally so that my other functions can use it as well but I have no idea how to since I am using a csvtojson for converter which makes the whole thing very long and was wondering if this is the way to declare or no?
JS:
//require the csvtojson converter class
var Converter = require("csvtojson").Converter;
// create a new converter object
var converter = new Converter({});
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/myproject';
// call the fromFile function which takes in the path to your
// csv file as well as a callback function
var JSarray = converter.fromFile("./NTA-SAM-Inventory-List-Security-
Management-New_2017.csv",function(err, result, callback){
if(err){
console.log("An Error Has Occured");
console.log(err);
}
// the result of the conversion
console.log(result);
result.toArray(function(err,doc){
if(err) throw err;
console.log('ohhhhh');
return callback(null, doc);
}
});
var array=[JSarray(function(err,doc)] This is how I declare the array.
My array is doc and so I can return callback but how should I get the array considering I have converter.fromFile("./NTA-SAM-Inventory-List-Security-
Management-New_2017.csv" which is too long so do I omit it when declaring the array or am I doing it wrong ? Thanks.
Update
Just wanted to clarify if I did it correctly.
var JSarray = converter.fromFile("./NTA-SAM-Inventory-List-Security-M
anagement-New_2017.csv",function(err, result, callback){
// if an error has occured then handle it
if(err){
console.log("An Error Has Occured");
console.log(err);
}
// the result of the conversion
console.log(result);
result.toArray(function(err,doc){
if(err) throw err;
console.log('ohhhhh');
return callback(null, doc);
var myArray= doc;
GLOBAL.GlobalMyArray = myArray;
});
});
Is this correct following your answer in declaring it globally?
global variables are not considered good programming practice.
Though you can create a global object module and reference this modules in all other modules in your project and play with exposed properties from it.
A simple example to achieve this is as following in node.js:
Create module GlobalArray. This module will expose a singleton object of the class it defines. The constructor of this class creates member variable. This class now expose the member variable using methods such as Add, Get. The instance of this class is exported from the module.
// File: GlobalArray.js
class GlobalArray {
constructor(){
this.array = [];
}
Add(item) {
this.array.push(item);
}
Get(){
return this.array;
}
}
let globalArray = new GlobalArray();
module.exports = globalArray;
Module for the class which add data to Global Array can be created as following:
// File: Add.js
const globalArray = require("./GlobalArray");
class Add {
AddToGlobalArray(){
globalArray.Add("1");
globalArray.Add("2");
globalArray.Add("3");
globalArray.Add("4");
globalArray.Add("5");
}
}
module.exports = Add;
Module for the class which print data from Global Array can be created as following:
// File: Print.js
const globalArray = require("./GlobalArray");
class Print {
PrintGlobalArray(){
let array = globalArray.Get();
for(let i=0; i<array.length; i++){
console.log(array[i] + "\n");
}
}
}
module.exports = Print;
Both Add and Print modules used statement const globalArray = require("./GlobalArray") to reference the Global Array.
Now, we can use Add and Print modules by referencing them in index.js to add and print data respectively using the Global Array.
// File: index.js
const Add = require("./Add");
const Print = require("./Print");
// Creating object of Add module to add data to global array
let addObject = new Add();
addObject.AddToGlobalArray();
// Creating object of Print module to print data from global array
let printObject = new Print();
printObject.PrintGlobalArray();
After executing index.js, it renders the following output:
>node index.js
1
2
3
4
5
You can set an array global inside of a function by assigning it to the window object.
function myFunction() {
var myArray = new Array();
window.GlobalMyArray = myArray;
}
Once it is set you can use GlobalMyArray from anywhere.
Using Node.Js you can use global
function myFunction() {
var myArray = new Array();
GLOBAL.GlobalMyArray = myArray;
}
You can now access the array globally using GLOBAL.GlobalMyArray
In which case it is very useful to do:
GLOBAL.window = GLOBAL
Like in the web browser.
Below is my static.js file:
var Helper = {
console.log: function(){
},
Login: function(){
var name;
var password;
//rest of the code
}
}
module.exports = Helper;
And below is my test.js file:
var Helper = require('./static.js');
console.log("Test");
And I got some error from this line console.log: function(){} in static.js file.
What I want is nothing will show on terminal even I console.log('Test') because I write function(){} for console.log.
Is anything I did wrong?
Just overwrite console.log function in your script:
console.log = function() {};
Overwrite other log function too:
window.console.log = window.console.debug = window.console.info = window.console.error = function () {
return false;
}
I just figured out how to fix this problem.
I rewrite the function like below..
DisableConsole: function(DEBUG){
if(!DEBUG){
if(!window.console) window.console = {};
var methods = ["log", "debug", "warn", "info"];
for(var i=0;i<methods.length;i++){
console[methods[i]] = function(){};
}
}
}
and require this static.js file in my top component which mean every component under this main component will also include this static.js.
and call this function in the very beginning.
AppHelpers.DisableConsole(false);
You have this error because you're trying to create an object with a key console.log, but it is a syntax violation when using object literal syntax, because . dot is a special symbol.
Even if it worked, you wouldn't achieve what you want, since console.log is a global function and you are working with just a custom created object.
What you actually want to do is to silence the global function like this console.log = function() {};. Beware, however, that you won't be able to restore the old behaviour if you didn't save the original function: var oldConsoleLog = console.log.
There is also a module for it.
FileUtil.js:
exports.a = function(pre) {
var module = {}
module.writeStringToFile = function writeStringToFile() {
casper.log(pre + " succ");
};
return module
}
main.js:
var casper = require('casper').create();
var FileUtil = require('FileUtil').a('xxx')
FileUtil.writeStringToFile() //xxx succ
That works, but what I want is var FileUtil = require('FileUtil')('xxx') instead of require('FileUtil').a('xxx').
I tried exports = function(pre) ..., but it doesn't works.
So, how to make a custom CasperJS module with custom parameter?
If you want var FileUtil = require('FileUtil')('xxx') to be your object then you need to use module.exports. It can export a single object, which can even be a function:
module.exports = function(pre) {
var module = {}
module.writeStringToFile = function writeStringToFile() {
casper.log(pre + " succ");
};
return module
}
Of course, it would be a better form to rename the inner module variable to something else.
I'm trying to figure out how i could store different objects in a certain "namespace".
I have something like this:
app.js
// This is the startup script:
var MyApp = {}
MyApp.ui = {}
MyApp.ui = require('ui/MainWindow');
MyApp.ui = require('ui/SecondWindow');
// Doesn't exist anymore because the 2nd require overwrites the
// first include
MyApp.ui.MainWindow.test;
Then i also have MainWindow.js and SecondWindow.js, which looks like this:
var MainWindow = {
test: "Main"
}
exports.MainWindow = MainWindow;
var SecondWindow = {
test: "Second"
}
exports.SecondWindow = SecondWindow;
The exports.XXXWindow = XXXWindow basically makes that object available.
So in my app.js i try to store the MainWindow object in MyApp.ui. So i can call it like this:
MyApp.ui.MainWindow.test
Then i'd also like to add the SecondWindow object to that. So i can call that in the same way:
MyApp.ui.SecondWindow.test
But the way i have it now causes the second require to overwrite the first one. So it now only points to SecondWindow. What do i have to do so that i can call both objects from MyApp.ui ??
I suggest you to do (I'm sorry if code is not syntactically correct but I use coffeescript and I'm not used anymore to Javascript):
MainWindow.js
var MainWindow = function() {
return {test: 'Main'};
};
module.exports = MainWindow;
SecondWindow.js
var SecondWindow = function() {
return {test: 'Second'};
};
module.exports = SecondWindow;
app.js
var myApp = {
ui: {
MainWindow: require('MainWindow.js'),
SecondWindow: require(SecondWindow.js)
}
};
Now my personal opinion. I prefer to do:
app.js
var MainWindow = require('MainWindow'),
SecondWindow = require('SecondWindow'),
myApp = {
ui: {
MainWindow: new MainWindow(),
SecondWindow: new SecondWindow()
}
};
The second assignment of MyApp.ui will overwrite its old value. However, you could do the following:
function inject(obj_into,obj_from){
for(var x in obj_from)
obj_into[x] = obj_from[x];
}
MyApp.ui = {MainWindow:{},SecondWindow:{}};
inject(MyApp.ui.MainWindow,require('ui/MainWindow'));
inject(MyApp.ui.SecondWindow,require('ui/SecondWindow'));
You first initialize MyApp.ui with empty property objects MainWindow,SecondWindow and fill them with inject.
Here are 2 files:
// main.js
require('./module');
console.log(name); // prints "foobar"
// module.js
name = "foobar";
When I don't have "var" it works. But when I have:
// module.js
var name = "foobar";
name will be undefined in main.js.
I have heard that global variables are bad and you better use "var" before the references. 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. E.g.,
// module.js
var name = "foobar";
// export it
exports.name = name;
Then, in 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:
Scenario 1: Put the stuff in config files
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)
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
// 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
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.
// 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.
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();
}
}
a variable declared with or without the var keyword got attached to the global object. This is the basis for creating global variables in Node by declaring variables without the var keyword. While variables declared with the var keyword remain local to a module.
see this article for further understanding - https://www.hacksparrow.com/global-variables-in-node-js.html
Not a new approach but a bit optimized. Create a file with global variables and share them by export and require. In this example, Getter and Setter are more dynamic and global variables can be readonly. To define more globals, just add them to globals object.
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
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
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. So if you use a file for exporting a singleton object, it will cause issues here.
You can choose global, require.main or any other objects which are shared across files.
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:
window.variableToMakeGlobal = value;
Then you can access this variable from all modules (and more generally, from any Javascript context).