We're having an argument, which I hope you guys will help resolve.
Say I have a simple factory defined like this:
angular.module('myModule', [])
.factory('Fact', function() {
var Fact = function() {
var that = {};
that.var1 = [];
that.var2 = [];
return that;
};
var fact = {
get: function() {
return Fact();
}
};
return fact;
});
I found out that this code will be working if I write it like this:
angular.module('myModule', [])
.factory('Fact', function() {
var fact = {
get: function() {
return Fact();
}
};
return fact;
});
var Fact = function() {
var that = {};
that.var1 = [];
that.var2 = [];
return that;
};
Namely, I can take this code of the object Fact and put it in some other plain .js file, include it before the Angular one (in index.html file) and this "would work".
However, I'm trying to resolve an argument that this approach is not good (well, not an Angular approach at that) because then this Fact is "laying around on the global scope", which is not good.
In which circumstances would you say that this is/isn't a good solution?
Is there a way to include a "nonAngular" code (simple JavaScript code written in some .js file) into the Angular factory?
Between factories, services, providers, constants and values, there's not really a good reason to have any code outside of Angular's constructs unless it's third party code.
If it is, you won't have control over the way that the library, framework, etc registers itself. It might use the global scope, alternatively, it might provide a module export.
Where possible, the cleanest and safest way to include third party code inside Angular is with a build-step using a module bundler.
For instance, I want to use the hypothetical package foojs from inside Angular using browserify:
Install the package with npm
npm install --save foojs
Then use it like this.
var foojs = require('foojs');
var app = angular.app('myapp')
app.service('myservice', function() {
// here we can use foojs safely
});
You can also achieve similar things with WebPack.
The reason this is safer is because after the build step, all the modules will be wrapped inside a function that protects the global scope.
If you aren't able to use a module bundler, then the only option is to use the global scope and allow the third party code to bind onto the window object.
Related
My goal is to build a set of javascript tools for functional programming, to be used by our company's web developers. I've tried giving a look at the Underscore annotated source but I'm new with RequireJS and AMD, so it's a lot confusing for me.
To start I just want to have a variable that gets available when my library is imported.
In this case booleans is a module that has functions returning boolean values. For example: _myLib.booleans.isDefined(var) - returns true is var is a defined variable.
No I have RequireJS setup, but how do I make a variable available for usage?
My main.js:
requirejs(['app/booleans'], function (booleans) {
var _myLib = {};
_myLib.booleans = booleans;
return _myLib;
});
Of course _myLib is undefined, I suppose it's because it is not assigned to any scope.
Can anyone give me some lights on building this library?
Thanks in advance.
If you want to produce a proper AMD library, you need to set it so that it calls define to define itself as an AMD module.
define(['app/booleans'], function (booleans) {
var _myLib = {};
_myLib.booleans = booleans;
return _myLib;
});
If you called your file myLib.js and provided a good configuration to RequireJS for it to find it, then, when you want to use it, you can do:
require(["myLib"], function (myLib) {
myLib.booleans.isDefined("moo");
});
Or in another module:
define(["myLib"], function (myLib) {
myLib.booleans.isDefined("blah");
});
Thus far I've worked only with relatively small projects (and mostly alone), but this time I have to collaborate with other programmers... basically because of that I must plan the structure of the website very carefully for the avoidance of spending hours debugging the code.
At this point I suppose doing that in the following manner. I divide my code in modules and store each module in a separate file inside an object (or a function) with a made-up name (lzheA, lzheB, lzheC etc.) to avoid conflicts whether an object with the same name was used in an another piece of code. When the document is loaded, I declare a variable (an object) that I use as a main namespace of the application. Properties of the object are the modules I defined before.
// file BI.lib.js
var lzheA = {
foo: function() {
},
bar: function() {
},
}
// file BI.init.js
function lzheK() {
BI.loadPage();
}
// file BI.loadPage.js
function lzheC() {
var result = document.getElementById('result');
result.innerHTML = "that worked";
}
// and so on
var lzheA,lzheB,lzheD,lzheE,lzheF,lzheG,lzheH,lzheI,lzheJ;
// doing the following when the document is loaded
var BI = {
lib: lzheA,
menu: lzheB,
loadPage: lzheC,
customScripts: lzheD,
_index: lzheE,
_briefs: lzheF,
_shop: lzheG,
_cases: lzheH,
_blog: lzheI,
_contacts: lzheJ,
init: lzheK,
}
BI.init();
https://jsfiddle.net/vwc2og57/2/
The question... is this way of structuring worth living or did I miss something because of lack of experience? Would the made-up names of the modules confuse you regardless of the fact that each one used only twice - while declaring the variable and assigning it to a property?
I consider the namespaces a good option when you want to modularize applications in Javascript. But I declare them in a different way
var myModule = myModule || {}; // This will allow to use the module in other places, declaring more than one specificComponent in other js file for example
myModule.specificComponent = (function(){
// Private things
var myVar = {};
var init = function() {
// Code
};
return {
init: init // Public Stuff
};
})();
If you want to call the init method, you would call it like this
myModule.specificComponent.init();
With this approach, i guarantee that the module will not be overwritten by another declaration in another place, and also I can declare internal components into my namespaces.
Also, the trick of just exposing what you want inside the return block, will make your component safer and you will be encapsulating your code in a pretty way.
Hope it helps
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to load bootstrapped models in Backbone.js while using AMD (require.js)
I am currently creating a RESTful API for one of our projects and also wanted to provide a Javascript library to access it.
Since I like the AMD principle and using require.js, I would provide an AMD module as well.
The problem is: the initialization of the module would require some information like the API key on initialization.
How do I pass such parameters into a module upon initalization?
If you have something like:
define(['dep1', 'dep2', 'dep3'], function (dep1, dep2, dep3) {
var module = {
...
};
return module;
});
change it to:
define(['dep1', 'dep2', 'dep3'], function (dep1, dep2, dep3) {
var module = {
...
};
var init = function (options) {
// Initialize here
return module;
};
return init;
});
Then after requiring your module somewhere, you can call it to initialize. You might also want to look into the factory pattern if you need something more complex and return the factory.
require.js does not restrict you in what you return. It can be a simple object, a string, a function...
I think what your looking for is the ability to set config variables that get picked up by the module. Here is an example using require.js
How to load bootstrapped models in Backbone.js while using AMD (require.js)
One other possibility that came to my mind is to use a serverside script to manipulate the source of the module when you are requesting it.
For example when you have to pass an API-key into the module, you do the following:
Before you do your first define() call, put the following code:
require.config({
paths: {
api: 'https://api.example.com/api.amd.js?api_key=f615ac61&'
}
});
This enables you to simply require your API from anywhere like this:
require(['api'], function(api){
});
So the server recieves the request - maps it thorugh mod_rewrite to some script, takes the GET parameter and puts it on the correct place in the module sourcecode, then returns the custom source.
Thats the way I solved this by now and it works like a charm, without the need to change any behaviour of the developers and it makes use of functionality thats already built into requirejs.
I don't think you can do that with require.js, but you can with Frame.js or some other module library. In Frame you would do that like this:
//moduleName.js
(function(exports){
exports.moduleName = function(args){
// do stuff
}
})(window.exports);
// in main js file
var exports = {}; // global variable
Frame('moduleName.js');
Frame(function(next){
var myArgs = { ... settings ... };
exports.moduleName(myArgs);
next();
});
Frame.init();
Is it possible to use a namespaced variable, and then to reference the appropriate object when you initialize the specific library? Maybe I don't understand exactly what you want require.js to do, but it looks like you call it from your main.js in any event, so I'm pretty sure it would work... I don't think you can do it like <script = "require.js?apiKey=jsdfhjkfklsjkfdjks">
var libData = {
apiKey: "jsdfhjkfklsjkfdjks",
otherpram: "userIDorsomething"
}
require(libData.apiKey);
but if you needed to send the apikey in the url parameter of the page, you could use a script like this to get the parameters:
<script>
function getQueryParams(qs) {
qs = qs.split("+").join(" ");
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])]
= decodeURIComponent(tokens[2]);
}
return params;
}
// assuming the page is loaded like page.html?apikey=jsdfhjkfklsjkfdjks
apiKey = getQueryParams(document.location.search).apiKey;
// however you have to call require, pass the api key?
</script>