Define Config Variables For require() Lib - javascript

I am making a library in NodeJS and it requires some configuration variables
I want to be able to define those variables in the main js file, and be able to use them in the core.js file like so
var config1 = "stuff";
var config2 = "more stuff;
var db = require('./core.js'); //this file uses config1 and config2
Is there any way to do this WITHOUT using exports.config1 and including the file in core.js?
I'm sorry if this is obvious but I couldn't find anything on google.
EDIT
I used a class with constructor
var config1 = "stuff";
var config2 = "more stuff;
var tt = require('./core.js');
const db = new tt(config1, config2);

One way to do this is define them as global variables.
main.js
global.config1 = "stuff";
global.config2 = "more stuff;
Then you can access them in the main.js.
core.js
console.log(global.config1)
Also please note that global is deprecated. You'll see the following error.
(node:59502) DeprecationWarning: 'GLOBAL' is deprecated, use 'global'
Another thing to note is that you should be cautious with putting variables in the global scope.

Related

Babel not compiling global variable

I'm missing the var declaration when coding. I have preset-0 and transform-runtime installed. The console shows the following error:
key is not defined
This is the code I'm running:
let set = new WeakSet();
key = {}; // missing var
set.add(key);
console.log(set.has(key));
But when I added the var keyword everything is fine:
let set = new WeakSet();
var key = {}; // added var
set.add(key);
console.log(set.has(key));
The console outputs:
true
Which means I cannot create global variables at will with babel?
Not like that you cannot.
You can always assign variables to the window.MyKey = whateverValue from any file and access this value from any other file in your app. But that's not the best way to share data globally in your app.
Best approach would be to create a file, say MyFile.js
class MyFile {
constructor() {
this.MyKey = 10;
}
}
export default (new MyFile);
Now you can require this file anywhere in your app and access the same instance of MyFile. So,
randomFile.js
import MyFile from './MyFile'
MyFile.MyKey = 20;
This approach avoids polluting the global scope but you accomplish the same functionality.

Global vs local for commonjs memory titanium

I have a code repeated for every page in Titanium studio, so should i declare it in each individual page or in a global scope?
Something like this.
//app.js
test = require('test');
//page1.js
test= new test();
view.add(test.view);
exports.view = view;
//page2.js
test = new test();
view.add(test.view);
exports.view = view;
or should i do it like this
//app.js
//page1.js
var test = require('test');
view.add(test.view);
exports.view = view;
//page2.js
var test = require('test');
view.add(test.view);
exports.view = view;
my test.js is something like this
//test.js
function textField(){
this.view = Ti.UI.createView();
this.view.add(this.textField = Ti.UI.createTextField());
}
module.exports = textField;
Avoid populating the global scope at all times. As you are writing in a commonJS pattern make sure you are modular and always protect the global scope.
I always use App.js to reference a controller file eg.
var controller = require('/controller');
controller.loadApp();
Which then makes it very hard to populate the global scope.
Follow the second example you provided as the first time a module or file is required by using
require('foo')
it's placed into the applications memory, if another page or tab then calls the same require needing access to it it doesn't reload it, it just changed the pointer to that file, giving access to all of it's functions E.g your textField function.

Javascript: usage of require in Appcelerator Titanium

I am quite new to javascript and I am struggling with a simple problem. I have to split up codes into separate files. As an example I have a file called Database.js. In that file I have the following lines:
function Database(){
//someStuff
this.fetchAll = function(){
//some stuff
return something;
}
}
Now I want to use the Database.js code in the file app.js. So I write the following code in app.js:
var Database = require('Database');
var myDB = new Database();
var result = myDB.fetchAll();
However, I get the error Script Error = '[object Database]' is not a constructor (evaluating 'new Database()') at app.js (line 3).
What is my mistake?
Before you moving to the development, you need to understand thoroughly about CommonJS Modules in Titanium. Then it will be more simple for you. Also refer the require function
Let's come to your error. [ERROR] [object Database]' is not a constructor (evaluating 'new Database()') at app.js (line 3) means that the module you created is not constructor. Your constructor function might not return any value. Read simple usage of CommonJS module. I'm sure it will resolve your issue.
There is an alternative way, you can include your Database.js file in your app.js. You does not need to return anything and no need to use require function. You just need to use the include method. Just write Ti.include('Database.js'); inside your app.js and you can access all the global variables and functions inside the Database.js file
This question is old but it has not been answered yet. So i will just provide the answer for anyone who is visiting here.
You have to export you function as global. To do so you would declare it as below
exports.fetchAll = function Database(){
//some stuff
return something;
};
You can also declare the function so that it can be used globally as well as locally within the file
var fetchAll = function Database(){
//some stuff
return something;
};
exports.fetchAll = fetchAll;
Then assuming the file name is Database and it is in same folder as app.js, you can use it as below
var Database = require('Database');
var result = Database.fetchAll();
edit: This answer is javascript general and it's not oriented towards Appacelerator Titanium.
There is no such include or require in javascript. You can on the other hand do one of the following
Include a script tag before your script to include Database.js
<script type="text/javascript" src="Database.js" >
OR
Add it dynamically
function loadScript(url, callback)
{
// adding the script tag to the head as suggested before
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
// then bind the event to the callback function
// there are several events for cross browser compatibility
script.onreadystatechange = callback;
script.onload = callback;
// fire the loading
head.appendChild(script);
}
The problem seemed to be the usage of the variable name 'Database'. Maybe there is somewhere a name collusion.
I am sorry that I did not know that the usage of require is not a basic concept of js.
Just a quick guess here. If you use CommonJS then you have to tell what should be available outside of the module. The way you lay out that you have made the Database "object" you would need to add:
module.exports = Database;
somewhere in your module. I always put them at the end - but not sure that is a requirement.
You can also make individual functions available outside of a module by specifying:
exports.getMyDatabase = getMyDatabase;
Where "getMyDatabase" is a function you have specified in the module. I use this way to "hide" certain implementation details of some functions from the outside and just make available the functions I want the developer to be able to call ;-)
/John
I think this is the right usage of require js:
require(["Database"], function() {
var myDB = new Database();
var result = myDB.fetchAll();
});
http://requirejs.org/docs/jquery.html

why does this object declaration work in node.js and how to declare a static variable?

i have seen this code :
var myNet = require ("net");
and in some function:
function foo (x,y) {
var myNewNet = new myNet();
myNewNet.createServer(x,y);
}
why does the code above create a new object? what is the mechanism stands behind that?
one more question, how do i create a static var in node.js, for example a id number that has to be unique.
i came with this option for static variable:
var id =0;
and put it on the global scope, is it ok?
The require statement basically is like an import; it takes an external library and makes it available in your code.
If you ever look in an external module, you will notice that it's just normal node.js js code. It has EXPORT statements in it. Those statements are what gets made available when you require something. Check out http://howtonode.org/creating-custom-modules
There is a GLOBAL keyword in node.js you can use to make something global
GLOBAL.IP_ADDRESS = "..."
As #Raynos says, it's not usually a good idea to do that, so another options is to export a constant from a module, so you can create a module and do
exports.STATIC_CONSTANT = "";
and then once you import the module you can do
var mod = require('mymodule');
mod.STATIC_CONSTANT;
EDIT, to answer you comment, the line
var myNet = require("net")
causes myNet to be whatever the net module exports. It must be exporting a function, so
var newNet = new myNet()
creates a new instance of the net object. From there
myNewNet.createServer()
is just invoking a method on the object you just created.

Load "Vanilla" Javascript Libraries into Node.js

There are some third party Javascript libraries that have some functionality I would like to use in a Node.js server. (Specifically I want to use a QuadTree javascript library that I found.) But these libraries are just straightforward .js files and not "Node.js libraries".
As such, these libraries don't follow the exports.var_name syntax that Node.js expects for its modules. As far as I understand that means when you do module = require('module_name'); or module = require('./path/to/file.js'); you'll end up with a module with no publicly accessible functions, etc.
My question then is "How do I load an arbitrary javascript file into Node.js such that I can utilize its functionality without having to rewrite it so that it does do exports?"
I'm very new to Node.js so please let me know if there is some glaring hole in my understanding of how it works.
EDIT: Researching into things more and I now see that the module loading pattern that Node.js uses is actually part of a recently developed standard for loading Javascript libraries called CommonJS. It says this right on the module doc page for Node.js, but I missed that until now.
It may end up being that the answer to my question is "wait until your library's authors get around to writing a CommonJS interface or do it your damn self."
Here's what I think is the 'rightest' answer for this situation.
Say you have a script file called quadtree.js.
You should build a custom node_module that has this sort of directory structure...
./node_modules/quadtree/quadtree-lib/
./node_modules/quadtree/quadtree-lib/quadtree.js
./node_modules/quadtree/quadtree-lib/README
./node_modules/quadtree/quadtree-lib/some-other-crap.js
./node_modules/quadtree/index.js
Everything in your ./node_modules/quadtree/quadtree-lib/ directory are files from your 3rd party library.
Then your ./node_modules/quadtree/index.js file will just load that library from the filesystem and do the work of exporting things properly.
var fs = require('fs');
// Read and eval library
filedata = fs.readFileSync('./node_modules/quadtree/quadtree-lib/quadtree.js','utf8');
eval(filedata);
/* The quadtree.js file defines a class 'QuadTree' which is all we want to export */
exports.QuadTree = QuadTree
Now you can use your quadtree module like any other node module...
var qt = require('quadtree');
qt.QuadTree();
I like this method because there's no need to go changing any of the source code of your 3rd party library--so it's easier to maintain. All you need to do on upgrade is look at their source code and ensure that you are still exporting the proper objects.
There is a much better method than using eval: the vm module.
For example, here is my execfile module, which evaluates the script at path in either context or the global context:
var vm = require("vm");
var fs = require("fs");
module.exports = function(path, context) {
context = context || {};
var data = fs.readFileSync(path);
vm.runInNewContext(data, context, path);
return context;
}
And it can be used like this:
> var execfile = require("execfile");
> // `someGlobal` will be a global variable while the script runs
> var context = execfile("example.js", { someGlobal: 42 });
> // And `getSomeGlobal` defined in the script is available on `context`:
> context.getSomeGlobal()
42
> context.someGlobal = 16
> context.getSomeGlobal()
16
Where example.js contains:
function getSomeGlobal() {
return someGlobal;
}
The big advantage of this method is that you've got complete control over the global variables in the executed script: you can pass in custom globals (via context), and all the globals created by the script will be added to context. Debugging is also easier because syntax errors and the like will be reported with the correct file name.
The simplest way is: eval(require('fs').readFileSync('./path/to/file.js', 'utf8'));
This works great for testing in the interactive shell.
AFAIK, that is indeed how modules must be loaded.
However, instead of tacking all exported functions onto the exports object, you can also tack them onto this (what would otherwise be the global object).
So, if you want to keep the other libraries compatible, you can do this:
this.quadTree = function () {
// the function's code
};
or, when the external library already has its own namespace, e.g. jQuery (not that you can use that in a server-side environment):
this.jQuery = jQuery;
In a non-Node environment, this would resolve to the global object, thus making it a global variable... which it already was. So it shouldn't break anything.
Edit:
James Herdman has a nice writeup about node.js for beginners, which also mentions this.
I'm not sure if I'll actually end up using this because it's a rather hacky solution, but one way around this is to build a little mini-module importer like this...
In the file ./node_modules/vanilla.js:
var fs = require('fs');
exports.require = function(path,names_to_export) {
filedata = fs.readFileSync(path,'utf8');
eval(filedata);
exported_obj = {};
for (i in names_to_export) {
to_eval = 'exported_obj[names_to_export[i]] = '
+ names_to_export[i] + ';'
eval(to_eval);
}
return exported_obj;
}
Then when you want to use your library's functionality you'll need to manually choose which names to export.
So for a library like the file ./lib/mylibrary.js...
function Foo() { //Do something... }
biz = "Blah blah";
var bar = {'baz':'filler'};
When you want to use its functionality in your Node.js code...
var vanilla = require('vanilla');
var mylibrary = vanilla.require('./lib/mylibrary.js',['biz','Foo'])
mylibrary.Foo // <-- this is Foo()
mylibrary.biz // <-- this is "Blah blah"
mylibrary.bar // <-- this is undefined (because we didn't export it)
Don't know how well this would all work in practice though.
I was able to make it work by updating their script, very easily, simply adding module.exports = where appropriate...
For example, I took their file and I copied to './libs/apprise.js'. Then where it starts with
function apprise(string, args, callback){
I assigned the function to module.exports = thus:
module.exports = function(string, args, callback){
Thus I'm able to import the library into my code like this:
window.apprise = require('./libs/apprise.js');
And I was good to go. YMMV, this was with webpack.
A simple include(filename) function with better error messaging (stack, filename etc.) for eval, in case of errors:
var fs = require('fs');
// circumvent nodejs/v8 "bug":
// https://github.com/PythonJS/PythonJS/issues/111
// http://perfectionkills.com/global-eval-what-are-the-options/
// e.g. a "function test() {}" will be undefined, but "test = function() {}" will exist
var globalEval = (function() {
var isIndirectEvalGlobal = (function(original, Object) {
try {
// Does `Object` resolve to a local variable, or to a global, built-in `Object`,
// reference to which we passed as a first argument?
return (1, eval)('Object') === original;
} catch (err) {
// if indirect eval errors out (as allowed per ES3), then just bail out with `false`
return false;
}
})(Object, 123);
if (isIndirectEvalGlobal) {
// if indirect eval executes code globally, use it
return function(expression) {
return (1, eval)(expression);
};
} else if (typeof window.execScript !== 'undefined') {
// if `window.execScript exists`, use it
return function(expression) {
return window.execScript(expression);
};
}
// otherwise, globalEval is `undefined` since nothing is returned
})();
function include(filename) {
file_contents = fs.readFileSync(filename, "utf8");
try {
//console.log(file_contents);
globalEval(file_contents);
} catch (e) {
e.fileName = filename;
keys = ["columnNumber", "fileName", "lineNumber", "message", "name", "stack"]
for (key in keys) {
k = keys[key];
console.log(k, " = ", e[k])
}
fo = e;
//throw new Error("include failed");
}
}
But it even gets dirtier with nodejs: you need to specify this:
export NODE_MODULE_CONTEXTS=1
nodejs tmp.js
Otherwise you cannot use global variables in files included with include(...).

Categories