X things every JavaScript developer should know: Automatic Semicolon Insertion

As with many other things in JavaScript Automatic Semicolon Insertion is usually not a problem but it can occasionally bite you if you are unaware of it. What Automatic Semicolon Insertion does is really simple. It basically boils down to semicolons being optional in JavaScript and the parser  injecting them when it is appropriate. That might sound very nice, after all you can leave semicolons out and the right thing will happen. For example the following code, without a single semicolon, is completely valid and will print a sum of 3 as expected:

   1: console.log(add(1, 2))
   2:  
   3: function add(x, y) {
   4:     var sum
   5:     sum = x + y
   6:     return sum
   7: }

 

What basically happens is that the JavaScript parser adds a semicolon at the end of each line if that doesn’t cause the syntax to become invalid. See section 7.9.1 of the ECMA-262 standard or read it online here.

Now that might sound great but it turns out that Automatic Semicolon Insertion can cause some interesting issues :-(

JavaScript style rules

One thing you might have noticed that the normal style of writing JavaScript is different than that of C# or Java. Compare the JavaScript code above with the same C# code below:

   1: public int Add(int x, int y)
   2: {
   3:     int sum;
   4:     sum = x + y;
   5:     return sum;
   6: }

Besides the obvious difference with the typing and the required semicolons the open curly brace for the add function is on the same line as the declaration in JavaScript and the next line in C#. While the JavaScript conventions would work fine in C# the reverse is not always the case. If we reformatted the JavaScript to the following the code, in this case, would still run fine.

   1: function add(x, y)
   2: {
   3:     var sum
   4:     sum = x + y
   5:     return sum
   6: }

 

However if we would return an object literal and format our code the same way we would run into a problem. Consider the following code:

   1: console.log(add(1, 2))
   2:  
   3: function add(x, y) {
   4:     var sum
   5:     sum = x + y
   6:  
   7:     return
   8:     {
   9:          sum: sum
  10:     }
  11: }

You might expect this to print an object with a property sum containing the value 3. However the code prints “undefined”. Compare that with the following code that is only formatted differently:

   1: console.log(add(1, 2))
   2:  
   3: function add(x, y) {
   4:     var sum
   5:     sum = x + y
   6:  
   7:     return {
   8:         sum: sum
   9:     }
  10: }

 

This will print the expected object with a sum of 3.

 

Blame JavaScript Automatic Semicolon Insertion

This unexpected behavior is caused by semicolon insertion. instead of the code you most likely think will execute the following executes:

   1: console.log(add(1, 2));
   2:  
   3: function add(x, y) {
   4:     var sum;
   5:     sum = x + y;
   6:  
   7:     return;
   8:     {
   9:         sum: sum
  10:     };
  11: }


Notice the semicolon after the return statement?


That actually means return nothing, i.e. undefined, and just have some unreachable code on the next few lines. That is completely valid so that is what happens :-(


Best practices


The general advice, even though it doesn’t protect you is to always add semicolons and not leave it up the the JavaScript parser. It doesn’t really help a lot because the parser will still inject semicolons of it thinks it is appropriate. So the only real solution is to use the JavaScript formatting conventions and ensure that the open curly brace of the object literal is after the return statement. That way adding a semicolon there is invalid and you can be sure the right thing happens.


Unfortunately ‘use strict’ doesn’t help here either. It will prevent some errors but it doesn’t make semicolons required :-(


Enjoy!

X things every JavaScript developer should know: Comparisons

Another item of things every JavaScript developer should know is how comparisons work. Just like with some of the other JavaScript, or I should really say ECMAScript, features anything you know about C# or Java could actually be misleading here.

 

To == or to ===

One of the weird things is there are actually two comparison operators in JavaScript, the double and the triple equals. The == is called the equals operator, see section 11.9.1 of the ECMAScript standard, and was the original equality operator. Unfortunately the way this operator works is quite some cause for confusion and as a result the === or Strict Equals operator was introduced, see section 11.9.4 of the ECMAScript standard. It would have been nice if they had just fixed the original problem but if they had they would have broken existing JavaScript applications.

In general I would always advise you to use the Strict Equals Operator or === whenever you do a comparison unless you have a specific need for the behavior or the original operator.

 

What is the problem with ==

I mentioned that == has problems and should be avoided but its still helpful to understand these problems. These problems basically boil down to the fact that the == operator does type conversions if the two types being compared are not the same. For example the following all evaluate to true:

   1: 0 == "0" // true


   2: 1 == "1" // true


   3: 2 == "2" // true

Sounds reasonable enough right?

 

Unfortunately it isn’t quite that simple all of the following evaluate to false:

   1: false == "false" // false


   2: true == "true" // false

These might seem weird, especially since the following evacuates to true again:

   1: true == !!"true" // true

 
So what is going on here?
 

The Abstract Equality Comparison Algorithm

Section 11.9.3 of the ECMAScript standard describes what is happening here. If one operand is a number and the other a string, as was the case in the first examples, the string is converted to a number and the comparison is done based on those. So basically these comparisons where:
   1: 0 == 0 // true


   2: 1 == 1 // true


   3: 2 == 2 // true



 



So what was the case in the other two comparisons?



In these cases almost the same happens and the Boolean values are converted to a number. That leaves a number to string comparison where the string is also converted to a number. And the result of converting true and false to a number is 1 and 0 but the result of the string to number conversions is an invalid number or NaN. And NaN being not equal to any other number means those comparisons result in false.



So why did the last comparison true == !!”true” evaluate to true? Well simple the double bang operator !! is evaluated first and a non empty string is truthy. End result of that is the expression true == true and that is obviously true. Sounds reasonable but that also means that any non empty string will result in true, so even true == !!"false" evaluates to true :-(



 











Conclusion



The double equality operator is a confusing part of the JavaScript history. You are best of to avoid it an use the Strict Equals Operator === instead.



 



Enjoy!

Converting the RavenDB Northwind database to a more denormalized form

In a previous blog post I demonstrated how to denormalize the RavenDB sample database and use the DenormalizedReference<T> and INamedDocument types from the RavenDB documentation to make life really sweet. That leaves us with one small problem and that is that the original sample database doesn’t work with our improved document design. With the sample database, small as it is, loading all document as a dynamic type, converting them and saving them would be easy enough but in a real database that would not be practical. So lets look at a better solution fixing the database.

 

Updating the database on the server

Instead of downloading each document, updating the structure and saving it back to the server it is much better to do these sort of actions on the server itself. Fortunately RavenDB has the capability to execute database commands on the server. These update commands can be PatchRequest objects that will let you do a large number of things using a nice C# API. And a the ultimate fallback there is the ScriptedPatchRequest which will let you execute a block of JavaScript code on the server. Why JavaScript? Well RavenDB stores things in JSON and the server is really not dependent on a .NET client.

Using the ScriptedPatchRequest we can either execute a patch on a single document or on a collection of documents. In this case I want to update all Order documents to reflect their new structure. It turns out this is quite simple

 

   1: using (IDocumentStore documentStore = new DocumentStore


   2: {


   3:     ConnectionStringName = "Northwind"


   4: }.Initialize())


   5: {


   6:     var javaScript = @"...";


   7:     


   8:     documentStore.DatabaseCommands.UpdateByIndex(


   9:         "Raven/DocumentsByEntityName",


  10:         new IndexQuery


  11:         {


  12:             Query = "Tag:Orders"


  13:         },


  14:         new ScriptedPatchRequest


  15:         {


  16:             Script = javaScript


  17:         });


  18: }

This code will execute the JavaScript code to patch the document once for each document in the Orders collection.

 

The JavaScript code to execute is quite simple, just make the changes required to the document and you are set.

   1: var company = LoadDocument(this.Company); 


   2: this.Company = {Id: this.Company, Name: company.Name};


   3:  


   4: var employee = LoadDocument(this.Employee);


   5: this.Employee = {Id: this.Employee, Name: employee.FirstName + ' ' + employee.LastName};


   6:  


   7: var shipVia = LoadDocument(this.ShipVia); 


   8: this.ShipVia = {Id: this.ShipVia, Name: shipVia.Name};


   9:  


  10: this.Lines.forEach(function(line){


  11:     var product = LoadDocument(line.Product); 


  12:     line.Product = {Id: line.Product, Name: product.Name};


  13:     delete line.ProductName;


  14: });



 





In this case I am converting the Company, Employee, ShipVia and Product properties to have the new structure. Additionally I am removing the ProductName from the OrderLine as that is no longer needed.



 



Sweet :-)

Denormalizing data in RavenDB

One of the things with RavenDB, or NoSQL document databases in general, is that you don’t do joins to combine data. Normally you try to model the documents you store in such a way that the data you need for most common actions is stored in the document itself. That often means denormalizing data. When you first get started with document databases that feels strange, after all with relational databases we are taught to normalize data as much as possible and not repeat the same values. Where normalizing data is great for updates and minimizing the size of databases it is less than ideal for querying. This is because when querying we need to join various tables to turn abstract foreign keys into something that is actually understandable by the end user. And while relational databases are pretty good at joining tables these operations are not free, instead we pay for the that with every query we do. Now it turns out that most applications are read heavy and not write heavy. And as a result optimizing writes  actually hurts something like 99% of the database operations we do.

With document database like RavenDB we can’t even do a join action. When we normalize data the client actively has to fetch related data and turn those abstract identities to other documents into, for a user, meaningful values. Normally the documents in a RavenDB database are much more denormalized that similar data in a SQL server database would be. The result is that for most operations a single IDocumentSession.Load() is enough to work with a document.

 

That data makes sense to denormalize?

Not everything makes sense to denormalize, normally only relatively static data that is frequently needed is denormalized. Why relatively static data? Simple, every time the master document for that piece of data is updated all documents where it might be denormalized also need to be updated. And while not especially difficult it would become a bottleneck if it happened to often. Fortunately there is enough data that fits the criteria.

 

The RavenDB example data

The de-facto sample data for SQL Server is the Northwind database. And by sheer coincidence it so happens that RavenDB also ships with this same database, except now in document form. With lots of .NET developers being familiar with SQL Server this Northwind database is often the first stop at how a document database should be constructed.

image

As you can see in the screenshot from the RavenDB studio a relatively small number of collections replaces the tables from SQL Server. Nice :-)

image

The structure used to save an order is also nice and simple, just the Order and OrderLine classes saved in a single document.

   1: public class Order


   2: {


   3:     public string Id { get; set; }


   4:     public string Company { get; set; }


   5:     public string Employee { get; set; }


   6:     public DateTime OrderedAt { get; set; }


   7:     public DateTime RequireAt { get; set; }


   8:     public DateTime? ShippedAt { get; set; }


   9:     public Address ShipTo { get; set; }


  10:     public string ShipVia { get; set; }


  11:     public decimal Freight { get; set; }


  12:     public List<OrderLine> Lines { get; set; }


  13: }


  14:  


  15: public class OrderLine


  16: {


  17:     public string Product { get; set; }


  18:     public string ProductName { get; set; }


  19:     public decimal PricePerUnit { get; set; }


  20:     public int Quantity { get; set; }


  21:     public decimal Discount { get; set; }


  22: }

 

One missing thing

Nice as this may be there is one missing thing. Other than the product name being sold and it’s price there is no data denormalized. This means that if we want to display to the user for even the most basic of uses we will need to load additional document. For example the Company property in an order just contains the identity of a customer. If we want to display the order the very least we would have to do is load the company and display the customers name instead of its identity. And the same it true for the employee and shipper.

While this sample database is not denormalized it turns out is is quite easy to do so ourselves.

 

Denormalizing the RavenDB Northwind database

The first step is to store the related name along with each referred to identity as seen below.

image

 

The order is the same but this time we can do common user interaction operations with just the one document and not be required to load additional documents. It turns out this is quite easy to do. The RavenDB documentation has a nice description on how to do that using INamedDocument and DenormalizedReference<T>. Using this technique makes it really easy and consistent to work with denormalized data and create a document structure like the one above. The change to the Order and OrderLine classes are minimal. All I had to do is replace the string type Company property with one of type DenormalizedReference<Company>.

   1: public class Order


   2:  {


   3:      public string Id { get; set; }


   4:      public DenormalizedReference<Company> Company { get; set; }


   5:      public DenormalizedReference<Employee> Employee { get; set; }


   6:      public DateTime OrderedAt { get; set; }


   7:      public DateTime RequireAt { get; set; }


   8:      public DateTime? ShippedAt { get; set; }


   9:      public Address ShipTo { get; set; }


  10:      public DenormalizedReference<Shipper> ShipVia { get; set; }


  11:      public decimal Freight { get; set; }


  12:      public List<OrderLine> Lines { get; set; }


  13: }


  14:  


  15: public class OrderLine


  16: {


  17:     public DenormalizedReference<Product> Product { get; set; }


  18:     public string ProductName { get; set; }


  19:     public decimal PricePerUnit { get; set; }


  20:     public int Quantity { get; set; }


  21:     public decimal Discount { get; set; }


  22: }

 

The DenormalizedReference<T> and INamedDocument are also really simple and straight from the RavenDB documentation.

   1: public class DenormalizedReference<T> where T : INamedDocument


   2: {


   3:     public string Id { get; set; }


   4:     public string Name { get; set; }


   5:  


   6:     public static implicit operator DenormalizedReference<T>(T doc)


   7:     {


   8:         return new DenormalizedReference<T>


   9:         {


  10:             Id = doc.Id,


  11:             Name = doc.Name


  12:         };


  13:     }


  14: }


  15:  


  16: public interface INamedDocument


  17: {


  18:     string Id { get; }


  19:     string Name { get; }


  20: }

 

The implicit cast operator in the DenormalizedReference<T> makes using this really simple. Just assign a property and it will take case of the proper reference needed.

   1: var order = session.Load<Order>("orders/42");


   2: order.Company = session.Load<Company>("companies/11");

 

One useful extension method

Loading the single document and doing common operations should be easy now but there are still operations where you will need more data from the related entity. Loading them is easy enough.

   1: var customer = session.Load<Company>(order.Company.Id);

 

However using the DenormalizedReference<T> the structure and type is already captured in the Order class. Using this with a simple extension method makes the code even simpler which is always nice :-)

   1: public static class IDocumentSessionExtensions


   2: {


   3:     public static T Load<T>(this IDocumentSession session, DenormalizedReference<T> reference)


   4:         where T : INamedDocument


   5:     {


   6:         return session.Load<T>(reference.Id);


   7:     }


   8: }

 

This simple extension method will let is load the customer as follows:

   1: var customer = session.Load(order.Company);





 



Saves another few keystrokes and completely type safe. Sweet :-)



 



Enjoy!

Tracking dirty objects in AngularJS

Tracking if an object is changed or not in AngularJS is quite easy but is also part of the UI so not always completely obvious. If you want to see if there are changes the $scope or the model will not tell you. Instead you need to take a look at the ngForm FormController. It has a $dirty flag that will tell you if an object is dirty or not. Saving that to the model itself is really easy, just use an ngForm directive, and the form element is automatically an ngForm directive, and the FormController will be added to the scope under the name you added, in the example below it is named frm. Next just set up a $watch() and Bob is your uncle :-)

 

   1: <!DOCTYPE html>


   2: <html>


   3: <head>


   4:     <style>


   5:         [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],


   6:         .ng-cloak, .x-ng-cloak {


   7:             display: none !important;


   8:         }


   9:     </style>


  10: </head>


  11: <body ng-app="app" ng-controller="demoCtrl">


  12:     <form name="frm">


  13:         <input type="text" ng-model="person.firstName" />


  14:         <hr />


  15:         {{person | json}}


  16:     </form>


  17:  


  18:     <script src="scripts/angular.js"></script>
   1:  
   2:     <script src="Script1.js">
</script>


  19: </body>


  20: </html>

 

   1: (function (angular) {


   2:     function demoCtrl($scope) {


   3:  


   4:         $scope.person = {


   5:             firstName:"Maurice"


   6:         };


   7:  


   8:         $scope.$watch("frm.$dirty", function(newValue) {


   9:             $scope.person.isDirty = $scope.person.isDirty || newValue;


  10:         });


  11:     }


  12:  


  13:     angular.module("app", [])


  14:         .controller("demoCtrl", demoCtrl);


  15: }(angular));



 



Enjoy!

X things every JavaScript developer should know: Truthy and falsy

One thing that developers often confuses with JavaScript is Boolean logic. It seems to simple, you use for example an if statement and put a boolean expression in there and if it is true the block of code is executed other wise the else block is executed. Something like this:

   1: (function () {


   2:     var data = [];


   3:  


   4:     if (data.length > 0) {


   5:         console.log("The data array is not empty");


   6:     } else {


   7:         console.log("The data array is empty");


   8:     }


   9: }());

 

And if you run it it will do exactly what you would expect, so what is the big deal here?

 

There is more to Boolean logic in JavaScript

Well it turns out that most JavaScript developers don’t write the code like this. In fact the code would probably look more like this:

   1: (function () {


   2:     var data = [];


   3:  


   4:     if (data.length) {


   5:         console.log("The data array is not empty");


   6:     } else {


   7:         console.log("The data array is empty");


   8:     }


   9: }());

Instead of comparing the array length to a number the array length is used as the actual boolean operator. But that is a number so what gives?

 

Instead JavaScript uses Truthy and Falsy

Instead of just using booleans JavaScript actually uses truthy and falsy instead. The rules are actually quite simple, a few values are considered to be falsy and all others are truthy. The falsy ones are:

  • false (obviously)
  • The number 0.
  • The empty string “”.
  • null
  • undefined
  • NaN (Not a Number)

Everything else is considered to be truthy!

 

This is why the test if (data.length) actually works the same as the first example. If the data array is empty the length is 0 and therefore falsy. Otherwise the length is larger than 0 and it is truthy.

 

Common JavaScript logic

In JavaScript this falsy behavior is commonly for all sort of logic, for example:

   1: function doSomething(options) {


   2:     options = options || {};


   3:     // Do something usefull with the options object


   4: }


   5:  


   6: doSomething();


   7: doSomething({});

 

In the function doSomething we basically check if the options if truthy. If it is passed the way it is supposed to, like in the second call, it will be thruthy and the value will be used as is. On the other hand if it is not passed the value will be undefined, which is falsy, and the logic will default it to the empty object. This is what happens in the first call.

 

The double bang operator

One trick that sometimes baffles people when they first see it is the double bang operator !!. Just like with many other languages the ! operator inverts a boolean expression. In the case of JavaScript it’s effect is to turn a truthy/falsy expression into the equivalent opposite and then back into the equivalent boolean of the original expression. Often used if you need to pass a boolean value and want to make sure some other code can’t misbehave with the variable passed.

   1: (function () {


   2:     var data = [];


   3:     var noData = null;


   4:  


   5:     console.log(!!data); // true


   6:     console.log(!!data.length); // false


   7:     console.log(!!noData); // false


   8: }());



 



It might look weird the first time you see it but once you understand the way JavaScript works it makes perfect sense :-)



 



Enjoy!

X things every JavaScript developer should know: use strict

In the previous blog post I explained that you should normally use an Immediately-Invoked Function Expression (IIFE) to give variables function scope. That works fine as log as we remember to declare our variables using the var keyword. However when we forget the var keyword we are back to the original problem as the variables are added to the global scope.

 

Leaking undeclared variables

As you can see in the two code snippets below the text variables are not declared using var. Even though they are only used inside a function they are still added to the global scope. The end result is that the variables are added to the window object and the second scripts overwrites the variable from the first script. And JavaScript being really relaxed doesn’t really case about missing var keywords, it will just do its thing, however wrong the result may be :-(

 

   1: (function() {


   2:     text = "Hello from script 1";


   3:  


   4:     setTimeout(function () {


   5:         console.log(text);


   6:     }, 1000);


   7: }());


   8:  

 
 
   1: (function() {


   2:     text = "Hello from script 2";


   3:  


   4:     setTimeout(function () {


   5:         console.log(text);


   6:     }, 1000);


   7: }());

 

These two scripts result in the following output:

image

 

Running JavaScript in strict mode

Fortunately there is a way that the JavaScript runtime can help us prevent this. The way to do that is by adding the string ‘use strict’ to our code. This might seem a bit strange as it is just a string. The reason for this is that it was added in ECMAScript 5 and doing it this way doesn’t cause an error in older browsers. All they see is a string that is not assigned to a variable. Not very useful but not an error either.

Just like variables ‘use strict’ is scoped to a function. So adding it applies it to that function and all nested ones. You could also add it outside of a function scope but that would change the default for all JavaScript executed in that window. This is because it changes the global scope and all other functions are defines as children of that global scope. In all likelihood you will be using some third party library and you cannot really know if all of them are compatible with ‘use strict’ so never go and change the global scope.

 

Adding ‘use strict’ to the IIFE in script2.js produces the following result. As you can see it only affects script2.js and that now throws and error about the missing var statement while script1.js runs unaffected.

   1: (function () {


   2:     'use strict';


   3:     text = "Hello from script 2";


   4:  


   5:     setTimeout(function () {


   6:         console.log(text);


   7:     }, 1000);


   8: }());

 

image

 

Other effects of ‘use strict’

In this case I am mostly concerned about using ‘use strict’ to find missing variable declaration it actually does more than just that. It will disable a number of potential dangerous JavaScript features. One of the other things it disables is using the call stack from a JavaScript function. See this article for more information.

 

 

The drawback of ‘use strict’

While I would live to recommend that you always use ‘use strict’ it turns out there are a few potential issues. While ‘use strict’ is scoped the function and nested functions it turn out it also affects non nested functions that might be called. I mentioned the fact that walking the call stack is disabled. However the way this is done is not consistent between browsers and can result in unexpected results. Take the following program:

   1: (function() {


   2:     function printCaller() {


   3:         var fn = arguments.callee;


   4:         while (fn) {


   5:             console.log(fn.toString().split("\n")[0]);


   6:             fn = fn.caller;


   7:         }


   8:     }


   9:  


  10:     function doMoreWork() {


  11:         printCaller();


  12:     }


  13:  


  14:     function doWork() {


  15:         'use strict';


  16:  


  17:         doMoreWork();


  18:         console.log("All done");


  19:     }


  20:  


  21:     doWork();


  22: }());



 



The doWork() function enables ‘use strict’ and calls doMoreWork() which calls printCaller(). Neither of the last two run with ‘use strict’.



When run in Chrome this produces the following result:



image



With FireFox we see the following:



image



And with Internet Explorer 11 we get the following:



image



Both IE and FireFox throw a runtime error when trying to read doWork() but Chrome just returns a null so the code doesn’t throw an error and continues.



The reason this turns out to be an issue for some people is that the Microsoft AJAX libraries contain similar stack walking code that starts failing on FireFox and IE as soon as you enable ‘use strict’. I am sure there are similar problems with other libraries but this is one Microsoft developers frequently run into if they are still using the AJAX libraries.






Conclusion



Use ‘use strict’ wherever you can but be aware of the differences in browser implementations that can trip you up.

X things every JavaScript developer should know: scoping

I see a lot of developer with a C# or Java background adopting JavaScript as well these days. Not that it should be a big surprise, lots of business applications are developed as client side browser based applications these days. And like it or not JavaScript is the language of the browser. Unfortunately the JavaScript syntax resembles that of Java or C# resulting in these developers thinking that they can easily master the language. And even though JavaScript is not a hard language to master there are some important differences and gotchas everyone needs to be aware of. So on these posts I am going to visit some of the things you just have to know. This time the scoping rules of JavaScript.

 

JavaScript scoping rules in the browser

JavaScript scoping rules in the browser are really very simple. There are just two scopes you can work with: global scope and function scope. Anything not defined in function scope is automatically global.

 

That seems simple enough but is very important and a lot of the structure of JavaScript is actually determined by this rule.

 

Seeing this in action is really simple. Suppose we take the following two scripts, each in its own JavaScript file:

   1: var text = "Hello from script 1";


   2:  


   3: setTimeout(function () {


   4:     console.log(text);


   5: }, 1000);

 

   1: var text = "Hello from script 2";


   2:  


   3: setTimeout(function () {


   4:     console.log(text);


   5: }, 1000);

 

Including these two scripts into an HTML page and loading then in the browser results in the following output:

image

The text variable of script 2 overwrites the variable from script 1 and we get the same message printed twice. Remember there is no file scope so both text variables are added to the global scope and the because they use the same name the second overwrites the first.

 

Fixing the problem with function scope

Fixing the problem basically means wrapping all the code in each file in a function. As we don’t actually need to reference the function anywhere else this is typically done with an Immediately-Invoked Function Expression (IIFE). See the code below:

   1: (function() {


   2:     var text = "Hello from script 1";


   3:  


   4:     setTimeout(function () {


   5:         console.log(text);


   6:     }, 1000);


   7: }());

 
   1: (function() {


   2:     var text = "Hello from script 2";


   3:  


   4:     setTimeout(function () {


   5:         console.log(text);


   6:     }, 1000);


   7: }());



Now the both text variables are scoped to the function they are contained in and no longer conflict. See the output below:



image



 



Conclusion



Wrapping all code in a JavaScript file in an IIFE is a simple little trick to make sure that everything has a private scope and nothing is leaked out unintentionally. All variables declared, and even more as we will see later, has function scope and this is a very important principal in JavaScript.



 



Enjoy!

AngularJS and loading data over HTTP

When creating an AngularJS controller that depends on some data that needs to be loaded over HTTP it’s really tempting and easy to just inject the $http service into your controller and load the data from there. And that is exactly what I did with the moviesListCtrl. But easy and convenient doesn’t make it the best way to do so!

 

Services: a better approach to HTTP

I strongly believe that a controller, regardless of AngularJS, MVC or WebAPI, should contain as little logic as possible. It  should just be the spider in the web and delegate to others when something needs to be done. In this case the work is loading data over HTTP and instead of doing that itself the controller should defer to some other service that is focused on just that.

 

Single Page Applications and state

It turns out there is another reason to separate the loading of data from the controller. A controller is reloaded each time the route changes. And if the controller loads the data that implies that the data will be reloaded on each navigation action. And indeed that was the case, the movies where reloaded each time the moviesListCtrl was reactivated. Now with some pretty dynamic data that might be exactly what you need but with something as static as a movie collection there is little point. And I would argue that in most applications that also applies to the majority of the data collections.

 

Creating a movies service

Creating a movie service is pretty easy. AngularJS has different ways of doing so but most of the time I use a factory. See this StackOverflow answer for more information about the different options. I basically moved the relevant code from the controller into a separate service and expose the required functions.

   1: module.factory("moviesSvc", function($http, $q) {


   2:     var movies = [];


   3:     var page = 0;


   4:     var genres, director;


   5:  


   6:  


   7:     function nextPage() {


   8:         var defer = $q.defer();


   9:  


  10:         var queryStr = "";


  11:         if (genres.length) {


  12:             queryStr = "&genres=" +


  13:                 genres


  14:                     .map(encodeURIComponent)


  15:                     .join("&genres=");


  16:         }


  17:  


  18:         if (director) {


  19:             queryStr += "&director=" + encodeURIComponent(director);


  20:         }


  21:  


  22:         $http.get("/api/movies?page=" + page + queryStr).then(function(e) {


  23:             [].push.apply(movies, e.data);


  24:             defer.resolve(!!e.data.length);


  25:         });


  26:         page++;


  27:  


  28:         return defer.promise;


  29:     }


  30:  


  31:     function query(genres1, director1) {


  32:         if (director !== director1)


  33:             movies.length = 0;


  34:  


  35:         genres = genres1;


  36:         director = director1;


  37:  


  38:         if (!movies.length) {


  39:             page = 0;


  40:             nextPage();


  41:         }


  42:  


  43:         return movies;


  44:     }


  45:  


  46:     return {


  47:         query: query,


  48:         nextPage: nextPage


  49:     };


  50: });

 

This greatly simplifes the controller making both much easier to develop and test.

   1: module.controller("moviesListCtrl", function($scope, $location, $window, genres, moviesSvc, director) {


   2:     $scope.loadingData = false;


   3:  


   4:     $scope.movies = moviesSvc.query(genres, director);


   5:  


   6:     $scope.nextPage = function() {


   7:         $scope.loadingData = true;


   8:  


   9:         moviesSvc.nextPage().then(function(newMoviesLoaded) {


  10:             $scope.loadingData = !newMoviesLoaded;


  11:         });


  12:     };


  13:  


  14:     $scope.filterByGenre = function(genre) {


  15:         genres.push(genre);


  16:         $location.path("/movies/genres/" + genres.join(","));


  17:     };


  18:  


  19:     $scope.showMoviePoster = function() {


  20:         var width = ($window.innerWidth > 0) ? $window.innerWidth : $window.screen.width;


  21:         return width > 767;


  22:     };


  23:  


  24:     $window.onresize = function() {


  25:         $scope.$digest();


  26:     };


  27: });


  28:  



 



Try it



The running application can be found here and the source on GitHub here.



 



Conclusion



Separating the HTTP requests from the controller makes code much easier to develop and test. And the side benefit is that the singleton nature of AngularJS services make it much easier to cache data and produce a faster and more efficient application.



 



Index of posts on the RAW stack



See here for more posts on the RAW stack.