New Posts  All Forums:Forum Nav:

AMD and Javascript.

post #1 of 9
Thread Starter 
I am trying to figure out how to convert my javascript code to use AMD style over whatever i am currently doing. The problem that i am running into is, that EVERYTHING i see basically sets a massive require array at the top... is that the right way, or the lazy way?
Code:
require(["dojo/dom",
            "dojo/on",
            "dojo/parser",
            "dojo/ready",
            "dijit/registry",
            "dojo/request",
            "dojox/xml/parser"

], function (dom,
            on,
            parser,
            ready,
            registry,
            request,
            xmlparser)
{

 ... bunch of code and methods without ever seeing a require again...

}

Please tell me this is just a lazy implementation of AMD.

1. If the method is used in multiple places, then it should be defined at the top, but if its only used in one function, that i should only load it there?

2. If its used in multiple methods, is it better to require for each of those functions instead of a global require?
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
post #2 of 9
It's generally better to compile your JS and then minify it. Consider using the closure compiler.

A working method I use (more or less) is below.
Code:
//this is a very basic script to do the trick
//consider it public domain and abuse it however you like
//but at your own risk.
//I DON'T recommend this for production use

var to_load = [
    "filename.js",          //what the file is
    "sub_folder/loader.js"  //this loads a second loader in a subfolder which loads those contents
];

var i, elem, len = to_load.length;
var frag = document.createDocumentFragment();

for (i = 0; i < len; i += 1) {
    elem = document.createElement('script');
    elem.setAttribute('type', 'text/javascript');
    elem.setAttribute('src', ('./scripts/js/' + to_load[i]));
    frag.appendChild(elem);
}

document.getElementsByTagName("body")[0].appendChild(frag);

Edited by hajile - 9/4/13 at 6:11pm
post #3 of 9
Thread Starter 
Hmm, i think i need to read up a bit more on this stuff and reword the question. Basically i have code like this https://developers.arcgis.com/en/javascript/jssamples/fl_hover.html . It just seems odd to have all the requires next to each other.

I will definitely look into minify. I'm mainly doing investigation work, but it would be nice to improve the performance without much work.
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
post #4 of 9
Quote:
Originally Posted by Mrzev View Post

Hmm, i think i need to read up a bit more on this stuff and reword the question. Basically i have code like this https://developers.arcgis.com/en/javascript/jssamples/fl_hover.html . It just seems odd to have all the requires next to each other.

I will definitely look into minify. I'm mainly doing investigation work, but it would be nice to improve the performance without much work.

If I understand you correctly, it is good programming practice to have all of your requires (or "includes", "imports", "use", etc as other languages call them) grouped at the start of your code because you can easily see what dependencies your code has without hunting through the code itself.

There's a lot of best practices when it comes to programming. Stuff that doesn't actually impact the execution of the code but does make a significant impact on how readable and maintainable your code is at any future point in time. Naming conventions for functions and variables is another such area. As is how you structure your functions, how deep you should nest conditionals and iterations, etc.

If you're struggling with how to layout your code, then I'd strongly recommend you have a read through the best practices for Javascript before wring any more code. you may not necessarily understand all the points just yet (and it doesn't matter if you don't), but it would save you a lot of time in the long run to get into good habits now smile.gif
post #5 of 9
Thread Starter 
Quote:
Originally Posted by Plan9 View Post

If I understand you correctly, it is good programming practice to have all of your requires (or "includes", "imports", "use", etc as other languages call them) grouped at the start of your code because you can easily see what dependencies your code has without hunting through the code itself.

Its more of the notation change.
Code:
dojo.require("dojo.parser")
dojo.require("dijit.form.ComboBox");
dojo.require("dijit.DropDownMenu");
dojo.require("dijit.MenuItem");

function blah()
{...}

to
Code:
require(["dojo/parser",
"dijit/form/ComboBox",
"dijit/DropDownMenu",
"dijit.MenuItem"
], function(parser, ComboBox, DropDownMenu, MenuItem)
{
function blah()
{..}
});


I think I understand now. I was thinking that the requires go at a function level, but really its there for the class level. I was mainly concerned that i am forcing to much in the global space, but thats not much of a problem since its only loading a small amount. I'm slowly learning the best practices with Javascript, but this AMD is just a bit unique on how the dependencies work compared to C++ or C#. I have grown accustomed to having a list of "using Blah.stuff;" at the top of the class. When I saw a bunch of dojo.require("dojo.parser") at the top, which is normal for me, to switch to require(["dojo/parser"], function(parser){...}); which wraps my functions into another function... just seems a tad odd. I guess I need to look at it like a namespace or a class... i need to read more =)

Probably a good idea on reading some more about best practices. I watched this google tech talk video last week on how to improve performance, and it blew my mind.

Thanks!
Edited by Mrzev - 9/5/13 at 9:26am
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
post #6 of 9

I use Dojo and AMD extensively. The way that you're loading your modules is correct and best practice. There's no cluttering of the global namespace, as all Dojo modules fall under Dojo, Dijit, or Dojox namespaces. 

 

To decrease the number of GET requests, we use a custom, minified build of Dojo for each project. It compiles all the required modules into a single file, and all dependencies are loaded from this file.

 

AMD has really changed the way we do our projects and made it all much easier to manage. Mostly because I can now write a separate module for each piece of functionality that I write in larger projects, making development much easier.

define([/*Load modules*/
    "dojo/dom",
    "dojo/on",
    "dojo/declare",
    "dojo/domReady!"], 
    function( dom, on, declare ){
        var foo = "Hi";
        return declare(null, {

             constructor: function(){
                 /*executes on module call*/
                 this.createInterface();
             },

             createInterface: function(){
                 var interface = dom.byId('container');
                 interface.innerHTML = "Hello World!";
             }
        }

})/*end define*/

This is a really simple example of a custom module.

Mini Trendy
(0 items)
  
Reply
Mini Trendy
(0 items)
  
Reply
post #7 of 9
Thread Starter 
I am still a bit unsure on the size of these modules, in a sense, what is a module considered? Is it a class? A group of Functions that are similar? A namespace? I converted all of my code, and while i was able to get it to work, i ended up creating some circular dependencies. Today i will be rewriting the conversion , this time after doing a bit of design work to avoid these loops. I am in the early stages of the project, and i just dont want to code myself into a corner.
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
post #8 of 9
Quote:
Originally Posted by Mrzev View Post

I am still a bit unsure on the size of these modules, in a sense, what is a module considered? Is it a class? A group of Functions that are similar? A namespace? I converted all of my code, and while i was able to get it to work, i ended up creating some circular dependencies. Today i will be rewriting the conversion , this time after doing a bit of design work to avoid these loops. I am in the early stages of the project, and i just dont want to code myself into a corner.

A quick sidenote on classes. JavaScript does NOT have classes. Since it is a prototype object system, it has only object which inherit from objects. Each object has a prototype (eg. myObj.prototype). When you append new (eg. var my_instance = new myObj(stuff)wink.gif the constructor prototype is called to initialize the sub-object. This sub-object isn't really an instance, just another object with it's own my_instance.prototype.constructor method for creating it's own instances if you want. Anything contained in myObj.prototype will be passed on to the child object. This whole system is clouded up by the JS designer trying to make it look more java-like. Douglas Crockford recommends the following which creates a method for the global object. This method takes an object to inherit from as an argument. It then creates an empty function and makes the soon-to-be inherited-from object it's prototype. A new object is returned (this new object has all the properties of object F and thus all the properties of F's prototype which is o thereby giving it all the properties of o.
Code:
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
//to use
newObject = Object.create(oldObject);

Anyway, JavaScript doesn't have modules built into the language. They are simply faked with closures and/or objects (as are namespaces -- they don't truly exist as in most languages). Therefore, modules can (even moreso than other languages) be whatever you want them to be. In most languages, a module does a specific task or related set of tasks. It may have one or more classes to accomplish this task. In JavaScript, a module should be a set of objects used to solve a specific task. The issue with AMD is that it prevents your modules from relying on any other modules. This may not seem like a problem, but JS is a very small language and doing anything significant either requires you to embed a library or load one before your module loads (which goes against the grain of asynchronous loading).

Your current problem with dependencies probably means you should put the dependent modules together. There are some alternatives. The first alternative is to refactor the code so that you ensure you NEVER call or access anything not in the module you're working in. The second is to load your modules in the order you desire (and if you compile them together in the order you want, it's even better). The final alternative is to create a depends() function that loads before all modules. When each module loads, it then calls depends("my_dependency"); depends("my_next_dependency"); etc. depends() then checks if these modules have been requested and loaded. If not, it will stop everything and generate a
Edited by hajile - 9/19/13 at 4:53pm
post #9 of 9
Thread Starter 
Quote:
Originally Posted by hajile View Post

A quick sidenote on classes. JavaScript does NOT have classes.

At least until EMCAv6 Harmony comes out for Javascript 2.0.


But yeah, i know Javascript doesnt have classes, but I'm trying to conceptualize the scope of a module for the library that I will be building overtime. Right now my code is 2000 lines long and I need to start splitting it up.

Simply put, its probably better to have several small modules than few large modules. I'm just not sure where the line is between function and some means of grouping.
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
Zev's Comp
(15 items)
 
  
CPUMotherboardGraphicsRAM
Intel Core i5-2500K Sandy Bridge 3.3GHz GIGABYTE GA-Z68X-UD3H-B3 LGA 1155 Intel Z68 HDM... GeForce GTX 750 Ti G.SKILL Ripjaws X Series 8GB 
Hard DriveHard DriveHard DrivePower
1TB HDD 64GB SSD (Used for SRT) 500 GB. Antec BP550 Plus 550W Continuous Power ATX12V V... 
Case
COOLER MASTER ELITE 335 RC-335-KKN1-GP Black S... 
  hide details  
Reply
New Posts  All Forums:Forum Nav:
  Return Home
  Back to Forum: Web Coding