pass variable between js files... in terminal - javascript

First of all, yes I know this question has been asked before, but I still cannot figure out how to make it work. I believe the problem is, I am running files individually through node.js on my Mac terminal, sorta like applications.
Here is the deal. I have one file, bitt1.js, that has var mid = 293.03;.
In my other file, otherFile.js, I have an if, else statement, depending on the variable mid (which is in bitt1.js):
if (mid <= 290) {
trade = true;
} else {
trade = false; }
The issue is, in terminal, I run first bitt1.js, then after I run otherFile.js. This makes it so I can't receive the mid variable from bitt1.js and it comes up as undefined.
How can I solve this issue? I've only found things used within html or etc, where the variables are always "available".
I'm new to JS and this whole thing so some of the stuff I said may be incorrect... and I could have also just been being dumb and the answer is obvious, but please help me out... I've thought about creating a JSON file and writing/reading data from it using the two other files, but I feel there's a better way...
Thanks!

Developer NodeJS's code works if you don't want to modify the value of the variable - if you just want to share the initial value of the variable, it works perfectly.
But if you intend to mutate the value of mid during runtime execution of bitt1.js and want to use that value, perhaps you can use a Unix pipe to plug its value into the stdin of bitt1.js.
E.g.
// bitt1.js
var mid = 299;
console.log("<mid>%d</mid>", mid); // this is piped to stdin
// otherFile.js
var stdin = process.openStdin();
var data = "";
stdin.on('data', function(chunk) {
data += chunk;
});
stdin.on('end', function() {
data.match(/<mid>([\s\S]+)<\/mid>/i);
var mid = +data.match[1];
console.log(mid);
});
Then running: node bitt1.js | node otherFile.js
Would print 299 from within otherFile.js.
This is a rough solution though: it should require some undefined checking on the match expression, and of course piping doesn't allow you to print anything directly to console in the bitt1.js file - you'd have to reprint everything in otherFile.js, which leads to duplicate code.
But it could be a solution that works for you, all depends on your requirements! Hope this helps.

node.js allows imports and exports.
Say bitt1.js has:
var mid = 299
console.log(mid)
// Here is where you export the desired value
//export default mid
module.exports.mid = mid
Then, in your otherFile.js
// you import the value from bitt1.js
var mid = require('./bitt1')
console.log(mid) //Outputs 299
That's it.
Edit: updated answer

Related

Node.js and Modules require. Objects are not assigned by reference?

I'm writing this question after 2 days of total struggling during which I couldn't find a solution but also couldn't find an explanation of why this code is not working.
I will report a super simplified simulation of my code.
I have 5 Node.js files:
1) server.js -> Is the main file used to start the server
2) globalVars.js -> Is where all the server "global" objects are stored.
3) globalFunctions.js -> Is where all "general" functions are stored to be used by all other modules
4) helloManager.js -> Example file which contains some standard function used by the server
5) aspect.js -> Same as helloManager.js
//server.js
//Loading the globalVars file. All objects are passed by reference so I use this to store the global variables
var globalVars = require("./globalVars.js");
//Assigning to the respective global object all the functions exported from other modules
globalVars.Modules.globalFunctions = require("./globalFunctions.js");
globalVars.Modules.aspect = require("./aspect.js");
globalVars.Modules.helloManager = require("./helloManager.js");
//After this point, the objects in globalVars.js will be populated with the respective functions exported from the files
//A timeout just to be sure it is not a problem of timing? (Well, it is not...)
setTimeout(function(){
console.log(globalVars.Modules.helloManager.helloOutput());
}, 2000);
/*
Console will throw the following error:
../globalFunctions.js:6
return "MR. " + aspect.getAspect();
^
TypeError: aspect.getAspect is not a function
*/
//globalVars.js
//Objects that will be populated with the functions inside other modules
module.exports.Modules = {
aspect: {},
helloManager: {},
globalFunctions: {}
};
//helloManager.js
var globalVars = require("./globalVars.js");
var { globalFunctions } = globalVars.Modules;
module.exports.helloOutput = function(){
return "hello " + globalFunctions.getHumanData();
};
//aspect.js
module.exports.getAspect = function(){
return "human";
};
//globalFunctions.js
var globalVars = require("./globalVars.js");
var { aspect } = globalVars.Modules;
module.exports.getHumanData = function(){
return "MR. " + aspect.getAspect();
};
Please don't answer me to put everything in the same file, because my code is way more complicated to report so here I'm posting this very simple simulation.
I know that objects are assigned by reference and so if all modules get the variables from "globalVars" they works kinda like "global".
The problem is when in globalFunctions.js I load
var { aspect } = globalVars.Modules;
Since in server.js the module aspect.js is not loaded yet, it will be an empty object.
But I'm expecting that
var { aspect } = globalVars.Modules;
is getting the reference of globalVars and not a copy, so when server.js finishes loading all the modules, the variabile aspect inside globalVars.Modules will point to the correct object and so it would find the function I need!
Infact the console.log inside server.js is executed after all modules have been loaded for this exact reason.
Does anyone know what is the reason of this problem and how could I solve it?
Thank to everyone who will help!
What's happening
It's an issue of what it means to do const { aspect } = globalVars.Modules; (which is the same as const aspect = globalVars.Modules.aspect;). That is, it's a matter of assignment semantics.
Let's look at a simpler example, then we can see hot it applies to what you're doing. Assume you have:
let a = {/*original object*/};
When you do
b = a;
the value in a is copied into b. That value is an object reference, so they now both point to the same object, but there is no ongoing link between a and b. If you then do
a = {/*new object*/};
that has no effect whatsoever on b, because there's no ongoing link between a (the variable) and b (the variable). b still refers to the original object, not the new one.
The same is true of any assignable item, such as an object property or parameter. That's what's happening with globalVars.Modules.aspect. globalFunctions is grabbing the value (simple assignment semantics, though using destructuring), then server.js is replacing that value with a new one.
Here's how that's happening in your code:
// server.js
var globalVars = (function() {
// globalVars.js
return { // this is the `exports` object
Modules: {
aspect: {}, // *** That's the `a = {/*original object*/}`
}
};
})();
// back in server.js
globalVars.Modules.globalFunctions = (function() {
// globalFunctions.js
const { aspect } = globalVars.Modules; // **** That's the `b = a`
return { // this is the `exports` object
getHumanData: function(){
return "MR. " + aspect.getAspect();
}
};
})();
// back in server.js
globalVars.Modules.aspect = (function() { // *** that's the `a = {/*new object*/}
return { // this is the `exports` object
getAspect: function(){
return "human";
}
};
})();
// back in server.js
globalVars.Modules.globalFunctions.getHumanData(); // Fails because the object it's using
// is the old one, not the new one
How to fix it
globalFunctions.js relies on aspect.js, so have it rely on it directly:
// In `globalFunctions.js`
const aspect = require("./aspect.js");
module.exports.getHumanData = function(){
return "MR. " + aspect.getAspect();
};
Assuming there are no cycles, that'll work.
At a larger level: There may be no reason to have globalVars.Modules at all. A module is only loaded once (normally), so rather than globalVars.Modules, just have each module directly rely on the module it needs, rather than funnelling it all through a central object. Node.js' module cache is already the central object.
If you don't want globalFunctions.js to rely on aspect.js directly (why not?), then don't copy the aspect property from Modules, use it as of when you need it:
// In `globalFunctions.js`
const {Modules} = require("./globalVars.js");
module.exports.getHumanData = function(){
return "MR. " + Modules.aspect.getAspect();
};
That'll work assuming nothing reassigns Modules (which nothing seems to in the code you've shown). But again, it makes more sense to rely on aspect.js directly if you can.
It's kind of fun to note that this is one of the reasons that modern ESM modules don't use simple assignment semantics like CommonJS ones do. ESM wouldn't help your specific thing, because you're using your own globalVars.Modules object instead of using the module objects, but it solves a problem that people often had with CommonJS modules which, like your problem, was caused by expecting b (an imported value) to be affected when reassigning a (the exported value). The issue people would have with CommonJS happened mostly when there were cycles between two modules (circular dependencies, directly or indirectly). ESM solves this by making the imported binding (b in my example) a live binding to the exported binding (a in my example). This is the only place JavaScript has what you could argue is a form of pass-by-reference (references to variables).
As you've noticed, var { aspect } = globalVars.Modules; copies the current value of globalVars.Modules.aspect to the local variable aspect. It's just alternative syntax for var aspect = globalVars.Modules.aspect.
If you later change the value of globalVars.Modules.aspect to a new object (as opposed to mutating the object that is already there) then the local variable doesn't update.
If you want the most recent value then you need to continue accessing globalVars.Modules.aspect whenever you need it.

How to update string in console instead of repeat it [duplicate]

My node.js application has a lot of console logs, which are important for me to see (it's quite a big app so runs for a long time and I need to know that things are still progressing) but I'm ending up with thousands of lines of console logs.
Is it somehow possible to do a console.update that erases/replaces a console line rather than creating a new line?
Try playing with process.stdout methods instead on console:
process.stdout.write("Hello, World");
process.stdout.clearLine(0);
process.stdout.cursorTo(0);
process.stdout.write("\n"); // end the line
TypeScript: clearLine() takes -1, 0, or 1 as a direction parameter with the following meanings:
-1: to the left from cursor.
0: the entire line.
1 - to the right from cursor
Following #michelek's answer, you can use a function somewhat like this:
function printProgress(progress){
process.stdout.clearLine();
process.stdout.cursorTo(0);
process.stdout.write(progress + '%');
}
Sure, you can do this using a module I helped create: fknsrs/jetty
Install via
npm install jetty
Here's a usage example
// Yeah, Jetty!
var Jetty = require("jetty");
// Create a new Jetty object. This is a through stream with some additional
// methods on it. Additionally, connect it to process.stdout
var jetty = new Jetty(process.stdout);
// Clear the screen
jetty.clear();
// write something
jetty.text("hello world");
jetty.moveTo([0,0]);
jetty.text("hello panda");
Jetty is not super useful when used on it's own. It is much more effective when you build some abstraction on top of it to make your jetty calls less verbose.
Just use \r to terminate your line:
process.stdout.write('text\r');
Here's a simple example (wall clock):
setInterval(() => process.stdout.write(`clock: ${new Date()}\r`), 1000);
To write a partial line.
process.stdout.write('text');
process.stdout.write('more');
process.stdout.write('\n'); // end the line
If the volume of output is the real issue then you'll probably to rethink your logging. You could use a logging system that allows selective runtime logging to narrow your output to what you need.
// The sections we want to log and the minimum level
var LOG_LEVEL = 4;
var LOG_SECTIONS = ['section1', 'section2', 'section3'];
function logit(msg, section, level) {
if (LOG_SECTIONS.includes(section) && LOG_LEVEL >= level) {
console.log(section + ':' + msg);
}
}
logit('message 1', 'section1', 4); // will log
logit('message 2', 'section2', 4); // will log
logit('message 3', 'section3', 2); // wont log, below log level
logit('message 4', 'section4', 4); // wont log, not in a log section
if you see stdout exceptions like TypeError: process.stdout.clearLine is not a function in Debug Console window of Visual Studio Code (or Webstorm), run the app as external terminal application instead of internal console. The reason is that Debug Console window is not TTY (process.stdout.isTTY is false). Therefore update your launch configuration in launch.json with "console": "externalTerminal" option.
We can use log-update
const logUpdate = require('log-update');
logUpdate('this will be gone');
logUpdate('this will stay');
Among others, the answer by #michelek does the trick. However, when you start using this, you may run into Exception trouble when output gets redirected to a file or you are in a debugger or running in a linux screen-session, etc. You may see messages such as process.stdout.clearLine is not a function.
Therefore, at least add a test to check that the output is a 'TTY' and is able to do such things as 'clearLine()' and 'cursorTo()':
if (process.stdout.isTTY) {
process.stdout.write("Hello, World");
process.stdout.clearLine(0);
process.stdout.cursorTo(0);
process.stdout.write("\n"); // end the line
}

I cannot access the variable in the other script. (Module.exports don't work everywhere)

I have been having issues with module.exports.
I have 2 Scripts that use Discord.js, and i need to have a SetTimeout() variable that is common to both scripts to be able to use ClearTimeout() from each of them.
I tried to use:
//first script
var foo = 20;
module.exports.foo = foo;
//Second Script
var exp = require('./firstscript');
console.log(exp.foo);
This was a test, to see if i was doing it the wrong way, with a simple variable instead of my SetTimeout().
The test worked fine when i ran new scripts with the node command but with npm start on my 2 original scripts it returned 'undefined' while having the same syntax.
In every script is already a module.exports for the Discord.js event class like 'Ready' for exemple.
I'm running this bit of code outside the main module.exports at the top where the const are declared.
I wonder if this is causing my issue.
example:
//the code i'm talking about is here.
module.exports = class ReadyEvent extends BaseEvent {
constructor() {
super('ready');
}
async run(client) {
Thanks for your help. Ask me for clarification if needed.
EDIT:
I looked up on the internet to see if it was an issue with the module.export that was already present on the script. And it was.
Apparently you cannot have several module.export in a script if each one of them doesn't specify a variable:
//this doesn't work
module.exports.value = value;
module.exports = value2;
//this works
module.exports.value = value;
module.exportd.value2 = value2;
My problem was that the one already present was used by the 'discord.js compiler' to register every command so i couldn't modify it without breaking the bot.
I decided to put my timer in a new script named GlobalVars and it worked Perfectly fine.
I'm Satisfied that it works now. For me the issue is fixed but i would love to know if it is possible to export a variable WITH the discord.js module.exports syntax included.
From your Second Script variable, its seems to be requiring a folder and not a file, and I don't think folders are allowed.
Assuming you are requiring a script and not a folder:
First Mistake: When requiring, inside the brackets you must have quotation marks ("") or ('').
If it is a folder, add a / next to ./firstscript and assign it to the file you want to refer to.
var exp = require('./firstscript/THE_INTENDED_FILE');
...If firstscript is a json file:
var exp = require('./firstscript.json');
Extracting Variables from file
// Option 1:
console.log(exp.foo);
// Option 2:
const extract = exp.foo
console.log(extract);

How to reorganize/refactor large sets of static javascript data

I have some inline-javascript containing large datasets which are hard-coded into my PHP site:
var statsData = {
"times" : [1369008000,1369094400,1369180800,],
"counts" : [49,479,516,]
};
I'd like to refactor my code so that my variables are served with this structure:
[
[1369008000, 49],
[1369094400, 479],
[1369180800, 516],
]
However I have many files to update - are there any tools that would help automate this process?
Just create a new array then loop through the original one, and place the values according to the indexes:
var statsData = {"times":[1369008000,1369094400,1369180800,],"counts":[49,479,516,]};
var result = [];//Create a new array for results.
for (var i = 0; i < statsData.times.length; ++i){//Loop the original object's times property from 0 to it's length.
result.push([statsData.times[i], statsData.counts[i]]);//Push a new array to the result array in the new order that will contain the original values you acces throught the index in the loop variable.
}
console.log(result);
Also in your code you have two start [ in your object's counts attribute but only one ] closing it.
Carrying on from the comments; Trying to parse JS from a mix of PHP/HTML is horrible so if you are prepared to do some copying and pasting then - if it were me - I'd opt for a simple command-line tool. As your Javascript won't validate as JSON it doesn't make much sense to try and parse it in any other language.
I've knocked up a quick script to work with your current example (I'll leave it up to you to extend it further as needed). To run it you will need to install Node.js
Next, save the following where ever you like to organise files - lets call it statsData.js:
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(data){
try {
eval(data+';global.data=statsData');
processData();
} catch(e) {
process.stdout.write('Error: Invalid Javascript\n');
}
});
function processData(){
try {
var i, out = [];
while(i = data.times.shift())
out.push([i, data.counts.shift()||0]);
process.stdout.write('var statsData='+JSON.stringify(out)+';\n');
} catch(e) {
process.stdout.write('Error: Unexpected Javascript\n');
}
}
Now you have a CLI tool that works with standard I/O, to use it open a terminal window and run:
$ node path/to/statsData.js
It will then sit and wait for you to copy and paste valid javascript statements into the terminal, otherwise you could always pipe the input stream from a file where you have copied and pasted your JS to:
$ cat inputFile.js | node path/to/statsData.js > outputFile.js
cat is a unix command - if you are working on a windows machine I think the equivalent is type - but I'm unable to test that right now.

Windows 8 IndexedDB createObjectStore

Trying to build a Metro app using Javascript and having issues with IndexedDb. I cannot create an object store. My code is shown below. I'm doing this on success of the open() function.
dbReq.onsuccess = function (evt) {
var txn = evt.target.transaction;
var db = evt.target.result;
if (!db.objectStoreNames.contains("test")) {
var store = db.createObjectStore("test");
}
}
Every time, it throws an exception on the 'createObjectStore' call that says
0x800a139e - JavaScript runtime error: [object IDBDatabaseException]
Over here they talk about it and it's a nice example to look at too, but still, did not help me.
Notice that control hits the one line of code inside 'if' statement. So 'db' is not null and is valid. But I saw that the transaction is null - not sure if that is an issue or even if you are supposed to get a valid transaction back at this point.
Not sure why it was not working. Switched to using roaming settings and it is very easy to use.
roamingSettings.values[SETTING_NAME] = SETTING_VALUE;
To read, of course,
var temp = roamingSettings.values[SETTING_NAME];

Categories