So, I'm a big fan of creating global namespaces in javascript. For example, if my app is named Xyz I normally have an object XYZ which I fill with properties and nested objects, for an example:
XYZ.Resources.ErrorMessage // = "An error while making request, please try again"
XYZ.DAL.City // = { getAll: function() { ... }, getById: function(id) { .. } }
XYZ.ViewModels.City // = { .... }
XYZ.Models.City // = { .... }
I sort of picked this up while working on a project with Knockout, and I really like it because there are no wild references to some objects declare in god-knows-where. Everything is in one place.
Now. This is ok for front-end, however, I'm currently developing a basic skeleton for a project which will start in a month, and it uses Node.
What I wanted was, instead of all the requires in .js files, I'd have a single object ('XYZ') which would hold all requires in one place. For example:
Instead of:
// route.js file
var cityModel = require('./models/city');
var cityService = require('./services/city');
app.get('/city', function() { ...........});
I would make an object:
XYZ.Models.City = require('./models/city');
XYZ.DAL.City = require('./services/city');
And use it like:
// route.js file
var cityModel = XYZ.Models.City;
var cityService = XYZ.DAL.City;
app.get('/city', function() { ...........});
I don't really have in-depth knowledge but all of the requires get cached and are served, if cached, from memory so re-requiring in multiple files isn't a problem.
Is this an ok workflow, or should I just stick to the standard procedure of referencing dependencies?
edit: I forgot to say, would this sort-of-factory pattern block the main thread, or delay the starting of the server? I just need to know what are the downsides... I don't mind the requires in code, but I just renamed a single folder and had to go through five files to change the paths... Which is really inconvenient.
I think that's a bad idea, because you are going to serve a ton of modules every single time, and you may not need them always. Your namespaced object will get quite monstrous. require will check the module cache first, so I'd use standard requires for each request / script that you need on the server.
Related
I am working on supporting a REST API that literally has thousands of functions/objects/stats/etc., and placing all those calls into one file does not strike me as very maintainable. What I want to do is have a 'base' file that has the main constructor function, a few utility and very common functions, and then files for each section of API calls.
The Problem: How do you attach functions from other files to the 'base' Object so that referencing the main object allows for access from the subsections you have added to your program??
Let me try and illustrate what I am looking to do:
1) 'base' file has the main constructor:
var IPAddr = "";
var Token = "";
exports.Main = function(opts) {
IPAddr = opts.IPAddr;
Token = opts.Token;
}
2) 'file1' has some subfunctions that I want to define:
Main.prototype.Function1 = function(callback) {
// stuff done here
callback(error, data);
}
Main.prototype.Function2 = function(callback) {
// stuff done here
callback(error,data);
}
3) Program file brings it all together:
var Main = require('main.js');
var Main?!? = require('file1.js');
Main.Function1(function(err,out) {
if(err) {
// error stuff here
}
// main stuff here
}
Is there a way to combine an Object from multiple code files?? A 120,000 line Node.JS file just doesn't seem to be the way to go to me....not to mention it takes too long to load! Thanks :)
SOLUTION: For those who may stumble upon this in the future... I took the source code for Object.assign and back ported it to my v0.12 version of Node and got it working.
I used the code from here: https://github.com/sindresorhus/object-assign/blob/master/index.js and put it in a separate file that I just require('./object-assign.js') without assigning it to a var. Then my code looks something like this:
require('./object-assign.js');
var Main = require('./Main.js');
Object.assign(Main.prototype, require('./file1.js'));
Object.assign(Main.prototype, require('./file2.js'));
And all my functions from the two files show up under the Main() Object...too cool :)
At first each file works in its own scope, so all local variables are not shared.
However, as hacky approach, you may just add Main into global scope available everywhere by writing global.Main = Main right after you define it, please make sure that you require main file first in list of requires.
The better(who said?) approach is to extend prototype of Main later, but in this case you may need to update a lot of code. Just mix-in additional functionality into base class
file1.js
module.exports = {
x: function() {/*****/}
}
index.js
var Main = require('main.js');
Object.assign(Main.prototype, require('file1.js'));
Shure.
constructor.js
module.exports = function(){
//whatever
};
prototype.js
module.exports = {
someMethod(){ return "test";}
};
main.js
const Main = require("./constructor.js");
Object.assign( Main.prototype, require("./prototype.js"));
There's a set of JS modules representing similar OOP Classes: think of e.g. different types of backend tasks (SendEmailTask, WriteToDbTask, WriteToDiskTask), or different actions on a drawing canvas (DrawArc, DrawLine, DrawBezier). Those are just examples.
Each of those is a single JS file, with its own define, and they're all located in a common directory. In a client module that depends on all of those, the dependency list and argument list have to include each one of those separately, e.g. something like:
define([
'tasks/sendEmailTask', 'tasks/writeToDbTask', 'tasks/writeToDiskTask', ...
], function (SendEmailTask, WriteToDbTask, WriteToDiskTask, ...) {
/* ... */
/* ... new SendEmailTask(); */
/* ... new WriteToDbTask(); */
/* ... new WriteToDiskTask(); */
});
and they both must be updated everytime a new module is added to the set, e.g. MakeCoffeeTask, which seems to me as a BadThing™.
Is there a way to avoid those last issues? I was thinking of a couple of possible ways, but I don't know how to make them work:
Create a kind of namespace module. Each of those sub-modules depends on the namespace one and adds its definition to it. But than if the client too depends only on the namespace, how do you ensure that client gets loaded after all sub-modules?
Express both dependencies and arguments with some kind of wildcard, like 'tasks/*' for dependency and < no idea > for arguments.
You can make a different module for each section. For example: 'tasks/main'
in the Task main you can include all the files you need. and in the task main, all the function of task will be assigned. and you call high level functions. Take look :
define(['tasks/main'], function(task){
task.add('Project Status meeting');
task.SendEmailNotification('tAll');
});
in the task/main.js :
define(['tasks/sendEmailTask', 'tasks/writeToDbTask', 'tasks/writeToDiskTask',], function(sendEmailTask, writeToDbTask, writeToDiskTask){
var task = {
add = function(taskObj){
// write your code using writeToDbTask, writeToDiskTask
},
SendEmailNotification = function(whom){
// write your code using sendEmailTask, writeToDbTask, writeToDiskTask
};
return task;
});
does it help you ?
I was not able to find any other solution. This is what I came up with in the meantime... it is just an improvement over current situation, but I don't think it solves the posed issues.
// in tasks/taskNamespace.js or in any client code
define (function(require) {
var _taskArray = [
require('tasks/sendEmailTask'),
require('tasks/writeToDbTask'),
require('tasks/writeToDiskTask'),
/* ... , */
];
var TaskNamespace = {};
_taskArray.forEach(function (taskClass) {
TaskNamespace[taskClass.name] = taskClass;
});
return TaskNamespace;
});
It takes advantage of RequireJS Sugar syntax and of JS Function.name coming new feature, proposed in ES6.
What's the end result? You still have to manually add each Class to a list, but it's only one list instead of two. WHOA
We're developing a mobile application and we're trying to figure out the best approach to share javascript functions across the application.
At the moment we have individual files that simply have:
var LIB = {
URL: "http://localhost/service",
connect: function() {
// connect to server
$.ajax({ url: this.URL }); // etc etc
// call a private function?
this._somethingElse();
},
_somethingElse: function() {
// do something else
}
};
Then we simply call things like:
LIB.connect(); or LIB.disconnect();
across any file.
This also gives us access to LIB.URL as well.
My question is whether this approach is the best?
I've seen people use the following approach as well, but to what benefit?
var LIB = function () {
this.URL = "http://localhost/service";
this.connect = function () {
var myself = this;
// connect to server
$.ajax({ url: this.URL }); // etc etc
// call a private function?
myself._somethingElse(); // best way to invoke a private function?
};
this._somethingElse = function () {
// do something else
};
};
This requires the following:
var lib = new LIB();
lib.connect();
EDIT:
I've also seen the following:
window.lib = (function () {
function Library () {
}
var lib = {
connect: function () {
// connect to server
}
};
return lib;
}());
I'm slightly confused with all these options.
It just depends on which you like better. I (on a personal level) prefer the former, but to each his own. The latter does have the disadvantage of requiring to either remember to declare the new before using it, or having to keep track of a already created one.
Additionally, on a technical level the first one should get slightly (as in, barely noticeable) performance, as you don't have to compute a new function.
Edit Yes, the first way is definitely the fastest.
I highly recommend going with a module system. Until ES6 comes along (http://wiki.ecmascript.org/doku.php?id=harmony:modules), you will have to use a 3rd party library in order to do this.
Each object/class/util/etc is a module.
A module exports a public api, whereas consuming modules import other modules by declaring their dependencies.
Two "standards" that exist: AMD and CommonJS. In the browser, a library like RequireJS, which uses the AMD standard, is very popular. I recommend checking out their site first: http://requirejs.org/ and see their examples.
The main advantage here is that you only expose the public api, which allows you to create a sandbox of your functionality. It's also more explicit as it's really easy to see what your module depends on, instead of relying on global objects.
There are several different approaches to structuring JavaScript code for re-usability. You can research these and decide which is best. Me personally, I have used the second approach that you've outlined. However, I separate my code into sections and actually adhere to an MVVM structure. So for instance, I have a name space called models and view models. Each of my js files begins with:
window.[APP NAME].Models.[CLASS/MODULE NAME] or window.[APP NAME].Models.[CLASS/MODULE NAME]
So, let's say I have a namespace called mynamespace and I have a module/class called myclass. My js file would begin with:
window.MYNAMESPACE = window.MYNAMESPACE || {};
window.MYNAMESPACE.ViewModels = window.MYNAMESPACE.ViewModels || {};
window.MYNAMESPACE.ViewModels.MyClass = function () {
// a public function
this.func1 = function () {
};
// a private function
function func2() {
}
};
I would then consume that class by calling:
var myClassModel = new window.MYNAMESPACE.ViewModels.MyClass();
myClassModel.func1();
This gives you some nice encapsulation of your code. Some of the other patterns you can research/google are: Prototype Pattern, Module Pattern, Revealing Module Pattern, and the Revealing Prototype Pattern.
I hope that helps but if you have any questions on what I've just said, feel free to comment on this post.
This is my second weekend playing with Node, so this is a bit newbie.
I have a js file full of common utilities that provide stuff that JavaScript doesn't. Severely clipped, it looks like this:
module.exports = {
Round: function(num, dec) {
return Math.round(num * Math.pow(10,dec)) / Math.pow(10,dec);
}
};
Many other custom code modules - also included via require() statements - need to call the utility functions. They make calls like this:
module.exports = {
Init: function(pie) {
// does lots of other stuff, but now needs to round a number
// using the custom rounding fn provided in the common util code
console.log(util.Round(pie, 2)); // ReferenceError: util is not defined
}
};
The node.js file that is actually run is very simple (well, for this example). It just require()'s in the code and kicks off the custom code's Init() fn, like this:
var util = require("./utilities.js");
var customCode = require("./programCode.js");
customCode.Init(Math.PI);
Well, this doesn't work, I get a "ReferenceError: util is not defined" coming from the customCode. I know everything in each required file is "private" and this is why the error is occuring, but I also know that the variable holding the utility code object has GOT to be stored somewhere, perhaps hanging off of global?
I searched through global but didn't see any reference to utils in there. I was thinking of using something like global.utils.Round in the custom code.
So the question is, given that the utility code could be referred to as anything really (var u, util, or utility), how in heck can I organize this so that other code modules can see these utilities?
There are at least two ways to solve this:
If you need something from another module in a file, just require it. That's the easy one.
Provide something which actually builds the module for you. I will explain this in a second.
However, your current approach won't work as the node.js module system doesn't provide globals as you might expect them from other languages. Except for the things exported with module.exports you get nothing from the required module, and the required module doesn't know anything of the requiree's environment.
Just require it
To avoid the gap mentioned above, you need to require the other module beforehand:
// -- file: ./programCode.js
var util = require(...);
module.exports = {
Init: function(pie) {
console.log(util.Round(pie, 2));
}
};
requires are cached, so don't think too much about performance at this point.
Keep it flexible
In this case you don't directly export the contents of your module. Instead, you provide a constructor that will create the actual content. This enables you to give some additional arguments, for example another version of your utility library:
// -- file: ./programCode.js
module.exports = {
create: function(util){
return {
Init: function(pie) {
console.log(util.Round(pie, 2));
}
}
}
};
// --- other file
var util = require(...);
var myModule = require('./module').create(util);
As you can see this will create a new object when you call create. As such it will consume more memory as the first approach. Thus I recommend you to just require() things.
Are there any dangers/caveats one should be aware of when creating JavaScript namespaces?
Our project is fairly expansive and we are running a lot of JavaScript files (20+, expecting more). It is impossible to have any code maintainability without using namespaces, so we are implementing them like so:
var namespace1 = {
doSomething: function() {
...
},
doSomethingElse: function() {
...
}
}
And then to create hierarchies, we link them like so:
var globalNamespace = {
functions1: namespace1,
functions2: namespace2,
...
}
This works fine, but it is essentially a "trick" to make JS behave as if it did have namespaces. Although this method gets used a lot, most literature on this seems to focus on how to do it, and not whether there are any possible drawbacks. As we write more JS code, this is quickly becoming an integral part of the way our system works. So it's important that it works seamlessly.
Were there any situations in which this "induced" namespace system caused you errors, or otherwise needed special attention? Can we safely expect identical behaviour across all browsers?
The way you define namespaces in your example it appears to create globals out of each namespace so you end up with
window.namespace1
window.namespace2
window.globalNamespace
window.globalNamespace.namespace1
window.globalNamespace.namespace2
So if you have anything that clobbers window.namespace1 it will also clobber window.globalNamespace.namespace1
edit:
Here's how we got around this problem:
namespacing = {
init: function(namespace) {
var spaces = [];
namespace.split('.').each(function(space) {
var curSpace = window,
i;
spaces.push(space);
for (i = 0; i < spaces.length; i++) {
if (typeof curSpace[spaces[i]] === 'undefined') {
curSpace[spaces[i]] = {};
}
curSpace = curSpace[spaces[i]];
}
});
}
};
Then you use it like this:
namespacing.init('globalNamespace.namespace1');
globalNamespace.namespace1.doSomething = function() { ... };
This way you don't have to introduce new global variables and you can confidently add to an existing namespace without clobbering other objects in it.
Since you are basically adding functions to objects and those objects into other objects, I would expect each browser to handle this the same way.
But if you want modularity, why not use a (relatively) simple framework like require.js? That will allow you and your team to write code in a modular fashion and allows the team to 'import' these modules where needed:
require(["helper/util"], function() {
//This function is called when scripts/helper/util.js is loaded.
});
Require.js will take care of dependencies, and it will also prevent polluting the global namespace.
We use a similar system at work and it does the job just fine. I don't see any drawbacks there could be; it's just objects and properties. For that same reason, cross browser compatibility should be good. You can end up having to write some long names to resolve to a particular function, like Foo.Bar.Test.Namespace2.Function, but even then that can be solved by assigning it to a variable before hand.
This is how I'd recommend doing it, so you stay out of the global scope entirely except for your "base" namespace. We do something similar where I work. Let's say you work for Acme co, and want ACME to be your base namespace.
At the top of every file, you'd include:
if (!window.ACME) { window.ACME = {} }
Then you just go and define whatever you want in terms of that.
ACME.Foo = {
bar: function () { console.log("baz"); }
}
If you want a deeper level of namespace, you just do the same thing for each level.
if (!window.ACME) { window.ACME = {} }
if (!ACME.Foo) { ACME.Foo = {} }
This way each file can be tested independently and they'll set up the namespace infrastructure automatically, but when you compile them together or if you test multiple files simultaneously, they won't keep overwriting things that are already defined.