Angular Performance Cheat Sheet

The key to tuning performance in an Angular app is reducing the number of $$watchers so the $digest cycle has less work to do. The $digest cycle is a cornerstone of Angular, and runs whenever a model is updated. It goes through all the $$watchers on all the $scopes in your entire application and checks if any values have changed. This is a crucial feature, and is how data bindings produce the desired results, but we need to be careful we are not unnecessarily adding to the burden of this $digest cycle, by adding $scopes and $$watchers where we don’t need them.

This is a cheat sheet of some small things you can do to make a real impact on your application’s performance. I’ll go through each point in more detail below, but for those wanting a quick reference you can just check this list.

 

One-time bindings

When you are using a data binding but only want the value to be evaluated once, you can use one-time bindings. Angular will wait until the value is stable and then drop it from its $$watchers list. This is a really good quick fix performance improvement, but just be careful you are not too enthusiastic and remove a $$watcher where it was actually needed.

To use one-time bindings on interpolated values you just put 2 colons after the curly brackets, so this:

<h4>{{title}}</h4>
<p>{{description}}</p>

Can become:

<h4>{{::title}}</h4>
<p>{{::description}}</p>

Furthermore you can add it to other directives, such as ngIf, ngRepeat & ngClass

<div ng-if=”::animals” ng-repeat=”animal in ::animals”>
  <h4 ng-class=”::{‘text-blue’: animal.isMarine}”>{{::animal.name}}</h4>
  <p>{{::animal.description}}</p>
</div>

It might look a bit odd but I think it was a really great feature to introduce.

Back to top

ngIf vs. ngShow

Being thoughtful with the use of ngIf vs. ngShow/ngHide can also make a real difference. Visually, they more or less accomplish the same thing, but they are doing it in different ways; make sure you know the difference and apply the appropriate one to the situation.

ngIf is removing the element from the DOM completely whereas ngShow is just setting the CSS display property, so the element is still in the DOM but is just hidden. When you change the value of ngIf it costs quite a lot to actually change the DOM, however when you are just hiding an element with ngShow all of its $$watchers are still there. So you need to be considerate when deciding which is for you. ngIf removes the $$watchers but can cost you when the value is changed, and ngShow still has all the overhead of its $$watchers but costs relatively little to change its value. If the value isn’t going to change very much and there are a lot of $$watchers then ngIf is the right choice. If the value is going to be updated frequently and there are few $$watchers then ngShow is the good choice. For everything in between, just decide on what suits the circumstance best.

Back to top

$watchCollection

With Angular v1.1.4 $scope.$watchCollection was introduced which can help save some processing if you have been using $scope.$watch and setting the third parameter to true. $watch without the third parameter set to true watches the top level for changes whereas $watchCollection will watch for changes one extra level deep and perform a shallow reference check on the items there. It is ideal for watching an array of items, thus the name, but if you want a deep check of all the items in the array then you will need to go back to using $watch with the third parameter set to true.

To clarify things, here are some examples of where the different functions would be used

In the below examples $watch (no third parameter) will suffice:

$scope.animals = ["koala"];
$scope.$watch(animals, onAnimalsChange);

$scope.animals = [];
$scope.animals = null;
$scope.animals = [“bilby”, “bandicoot”, “bettong”];

$watchCollection will trigger from everything above and also:

$scope.animals = ["koala"];
$scope.$watchCollection(animals, onAnimalsChange);

$scope.animals.push(“bat”);
$scope.animals.splice(0, 1);
$scope.animals[0] = “bat”;

$watch with the third parameter set to true will trigger everything above and also is the only one that could be used in the below example:

$scope.animals = [{name: "koala", description: ""}];
$scope.$watch(animals, onAnimalsChange, true);

$scope.animals[0].description = “a fluffy grey marsupial"

Back to top

$scope.$on(“$destroy”)

When a controller or directive is destroyed it handles cleaning up its own scope, so any $$watchers or $$listeners will be automatically removed. However, if you have added anything to another $scope, such as $rootScope or $scope.$parent, make sure you clean these up by listening for the $destroy event

anguar.module(“myApp”).controller(“BilbyController”, 
    function($scope, $rootScope) {

        var bilbies = [];

        var bilbyAdded = $rootScope.$on(“bilbyAdded”, 
            function(event, newBilby) {
                bilbies.push(newBilby);
            });

        $scope.$on(“$destroy”, function(event) {
            // remove event listeners by invoking the returned function from their instantiation
            bilbyAdded();
        });
    });

You will also need to make sure to clear any $timeout or $interval calls you may have running.

anguar.module(“myApp”).controller(“BilbyController”, 
    function($scope, $rootScope, Bilbies) {
        $scope.bilbies = [];

        var bilbyRefreshInterval = $interval(function() {
            Bilbies.get().then(function(data) {
            $scope.bilbies = data;
        }, 60000);

        $scope.$on(“$destroy”, function(event) {
            $interval.cancel(bilbyRefreshInterval );
        });
    });

Back to top

ngModelOptions debounce

This is particularly useful if you have a text input that is triggering some sort of functionality, such as a search bar that is making requests to an API to search data. You can limit how frequently the model will update, and thus reduce how frequently the function is run. Wherever you have the ngModel directive you can add another called ngModelOptions, where you can set the debounce value in milliseconds.

<input type=”text” placeholder=”Search...” ng-model=”data.search” ng-model-options=”{debounce: 150}” ng-change=”getSearchResults()”/>

In this example the getSearchResults function will be called no more than once every 150ms regardless of how quickly the user is typing.

Back to top

JavaScript Filters

DOM filters can sometimes be an unnecessary overhead as they are executed twice every $digest cycle. Take this

<div ng-repeat=”bilby in bilbies | orderBy:’name’”>
  <h2>{{bilby.name | uppercase}}</h2>
  <p>{{bilby.description}}</p>
</div>

Whenever the $digest cycle is run the orderBy filter will be executed twice and then the uppercase filter will be executed twice per item in the array. This is a lot of overhead for an array that rarely changes.

You can speed things up by applying the filters in your JavaScript code to the data before it gets to the DOM. Angular allows you to inject any filter by using filter name + “Filter” into a controller (or service or directive…). So the above code could be tuned for performance like so

angular.module(“myApp”).controller(“BilbyController”,
    function($scope, Bilbies, orderByFilter, uppercaseFilter) {
        $scope.bilbies = [];

        Bilbies.get().then(function(data) {
            data = orderByFilter(data, “name”);
            for (var i = 0, len = data.length; i < len; i++) {
                data[i].name = uppercaseFilter(data[i].name);
            }
            $scope.bilbies = data;
        });
    });
<div ng-repeat=”bilby in bilbies”>
  <h2>{{bilby.name}}</h2>
  <p>{{bilby.description}}</p>
</div>

You can do exactly the same with any of your own custom filters.

This method is more work and more code; the pipes do look neater and tidier, but we have to make such sacrifices in the name of performance.

Back to top

ngRepeat

This can be one of the worst culprits of bad performance in Angular applications. If you have an ngRepeat directive looping over a large data set with a lot of directives and bindings and scopes in the repeated template you are going to run into a problem. Easier said than done, but try and avoid using ngRepeat where possible, and if you do, think about all of those scopes, bindings and directives. Do you need them all? If you have a large data set, do you need to display it all at once? Could you use pagination or infinite scrolling? It pays to be thoughtful about your code.

The Best of ES2015

The release of the ES2015 JavaScript specification brought a lot of new features to the JavaScript dev community. This was a fairly huge release and it can be a little overwhelming reading through it all, so here I have listed what I found to be my favourite new features.


LET

You can use the let keyword in place of the var keyword. When you use var, your JavaScript code undergoes what is know as hoisting. This means that behind the scenes all of the values declared in the scope using var are pulled to the top of the scope.

function getAnimals(isMarsupial) {
    if (isMarsupial) {
        var marsupials = [];
        return marsupials;
    } else {
        var otherAnimals = [];
        return otherAnimals;
    }
}

actually becomes:

function getAnimals(isMarsupial) {
    var marsupials;
    var otherAnimals;
    if (isMarsupial) {
        marsupials = [];
        return marsupials;
    } else {
        otherAnimals = [];
        return otherAnimals;
    }
}

This hoisting can cause errors that we are probably all familiar with – let’s look at an example. Here is a simple function that is looping over an array called items and calling a function send passing in each item. This function is asynchronous and receives a callback function as its second parameter. When the send function is successful, we want to reference the item and log that it sent successfully.

function sendItems(items) {
    for (var i = 0, len = items.length; i < len; i++) {
        send(items[i], function() {
            console.log("item sent: " + items[i]);
        });
    }
}

If I then call it like

sendItems(["Wombat", "Echidna", "Bilby"]);

I’m sure you can see what will happen here – the console output will read

Bilby
Bilby
Bilby

Introducing let.

If we use let in place of var here, there will be no hoisting and we will be able to reference our item in the same way and produce the desired result. Variables declared using let are scoped to the nearest block, which means anything in curly brackets – if statements, for loops, etc. So if we use let to declare the iterator variables, a new one will be created on each iteration rather than sharing the old one. So, our code becomes:

function sendItems(items) {
    for (let i = 0, len = items.length; i < len; i++) {
        send(items[i], function() {
            console.log("item sent: " + items[i]);
        });
    }
}

sendItems(["Wombat", "Echidna", "Bilby"]);

Which will now output:

Wombat
Echidna
Bilby

Using let can help us remove some of those annoying code anomalies which can drive you mad.


CONST

ES2015 introduced constants to the JavaScript language. If, like me, you have come to JavaScript from an object-oriented language you will understand what a constant is and probably be very happy to see them. If you haven’t heard of them, just think of a constant as a variable that can only be declared and never reassigned to.

As an example, in the following code I am checking how many animals are in an array, and if they reach 5 or more, printing a message to the console.

function checkAnimals(animals) {
    if (animals.length >= 5) {
        console.log("Too many animals");
    } else {
        console.log("A good amount of animals");
    }
}

The number 5 here is hard to understand, especially if you come back in 6 months or another developer looks at this. Why is it 5? Is this same number used anywhere else? What happens when the requirements change and the number needs to be updated? Will you find all the places it is used and change them all correctly?

We can use the const keyword to solve this problem.

const MAX_ANIMALS = 5;

function checkAnimals(animals) {
    if (animals.length >= MAX_ANIMALS) {
        console.log("Too many animals");
    } else {
        console.log("A good amount of animals");
    }
}

This is instantly much easier to understand and will be much easier to refactor when the requirement comes in. You could have previously just done the same thing using var, but const provides a few extra things. Namely, you cannot reassign a value to it, you declare it once and that’s it, it is now only read-only. Following from this, a constant must be declared with a value, you cannot create it and assign its value later. From the semantics side, constants help other developers understand your intent and purpose. The convention when declaring constants is to use all caps – again this just helps understand what is going on when someone (or future you) looks at your code. A nice benefit of using constants is that they result in better performance as the JavaScript engine also has a better understanding of your purpose.


FOR OF LOOP

This new loop enables you to loop over items in an array and just access the item values.

So this

for (let i = 0, len = animals.length; i < len; i++) {
    console.log(animals[i]);
}

becomes

for (let animal of animals) {
    console.log(animal);
}

Much simpler syntax, and quicker to write too. This is great for working with arrays when you are not concerned with the index.

The for of loop needs an iterator to work with. This means that it won’t work with an object out of the box, if you try you will seen an error like

TypeError:myObject[Symbol.iterator] is not a function

But if you are keen on getting this working for an object there is something you can do. You can create the iterator function yourself and assign it to the Symbol.iterator property of the object.

let brenda = {
    animal: "bilby",
    age: 24,
    colour: "grey"
};

brenda[Symbol.iterator] = function() {
    let properties = Object.keys(this);
    let count = 0;
    let isDone = false;

    let next = function() {
        if (count >= properties.length) {
            isDone = true;
        }
        return {
            done: isDone,
            value: this[properties[count++]]
        };
    };
    return {
        next: next
    };
};

The brenda object can now be looped over using the for of loop (or any other iterating loop)

for (var prop of brenda) {
    console.log(prop);
}

will output

bilby
24
grey

DEFAULT PARAMETERS

ES2015 introduced default function parameter values to JavaScript. This means you can assign a value to a parameter if none is provided in a nice non-hacky way. This will make your code easier to read, and also quicker to write.

Here is the pre-ES2015 way if you didn’t want your code to throw an error if a parameter wasn’t specified.

function listAnimals(animals) {
    animals = animals || [];
    for (let animal of animals) {
        console.log(animal);
    }
}

Now we can write this like

function listAnimals(animals = []) {
    for (let animal of animals) {
        console.log(animal);
    }
}

It looks clearer, and there are less lines of code to maintain and for someone else to have to read to understand what is going on.


REST PARAMETERS

This new syntax allows us to specify an indeterminate number of parameters as an array. So we could pass 2,5 or 20 parameters into a function and they would all be put into an array for us.

Let’s go back to that listAnimals function. Say we didn’t want to pass the function an array of animals, but just one parameter per animal. We would change it to use rest parameters by prepending 3 dots to the parameter name

function listAnimals(...animals) {
    for (let animal of animals) {
        console.log(animal);
    }
}

You can still have other parameters as well, but this one must go last.

function listAnimals(group, ...animals) {
    for (let animal of animals) {
        console.log(group + ": " + animal);
    }
}

You are basically saying “and put the rest of the parameters in here”. You could then call this function like so

listAnimals("marsupials", "bilby", "wombat", "kangaroo");
listAnimals("birds", "galah", "kookaburra");
listAnimals("canines", "dingo");

This is much tidier than using a function’s arguments array, and it won’t cause errors if we start adding new parameters to the function (providing we make sure to keep the rest parameters last).


ARROW FUNCTIONS

Arrow functions were probably one of the things that caused the most excitement with the release of ES2015. They can really help simplify a callback function – let’s have a look at an example.

Here is a function which takes a callback function as its second parameter

getAnimal(urlRequest, function(animal) {
    console.log(animal.name);
});

Now here it is again, written in the arrow syntax

getAnimal(urlRequest, (animal) => {
    console.log(animal.name);
});

We are able to remove the function keyword saving us some time and making our code easier to read. It doesn’t look overly impressive when used like this, but there is more. Say we were returning the animal’s name from our callback it could look even simpler.

getAnimal(urlRequest, (animal) => animal.name);

If you only want to return one thing from the function you can omit the curly brackets and just declare the return value. In this case it is looking much simpler and seems a bit more useful.

But the most helpful part of arrow functions for me is that they have a lexical scope. This means that the this keyword can be used to refer to the scope of its containing function. No more saving the value of this and reusing later.

var AnimalGroup = function() {
    this.animals = [];
};

AnimalGroup.prototype.addAnimal = function(urlRequest) {
    var that = this;
    getAnimal(urlRequest, function(animal) {
        that.animals.push(animal);
    });
});

becomes

var AnimalGroup = function() {
    this.animals = [];
};

AnimalGroup.prototype.addAnimal = function(urlRequest) {
    getAnimal(urlRequest, (animal) => {
        this.animals.push(animal);
    });
});

This to me was the biggest benefit, as it can be quite annoying to save the value of this and add what seems to be quite unecessary code to your project.


OBJECT INITIALISATION

A new shorthand way of creating objects has been introduced that lets you skip naming the property if you are going to us a variable with that same name as its value.

Here is an example of creating an object in the old ES5 syntax

function createAnimal(name, type) {
    var colour = getColour(type);
    return {
        name: name,
        type: type,
        colour: colour
    };
}

And what it can look like now

function createAnimal(name, type) {
    var colour = getColour(type);
    return { name, type, colour };
}

Again, it is just another thing to save you time and make your code cleaner and easier to read.


METHOD SYNTAX

ES2015 has introduced a new way of declaring methods on an object which will also help remove some of those keywords and make your code a little more readable and quicker to write. It looks a bit similar to the arrow function syntax.

So here is my original object with a method called countAll

var bilby = {
    colour: "grey",
    type: "marsupial",
    countAll: function(bilbies) {
        return bilbies.length;
    }
};

Using the new method syntax, I can now remove the function keyword entirely.

var bilby = {
    colour: "grey",
    type: "marsupial",
    countAll(bilbies) {
        return bilbies.length;
    }
};

TEMPLATE STRINGS

This probably looks very familiar to you

function displayCount(count) {
    console.log("I have " + count + " animals");
}

Using the plus symbol to insert a dynamic value into the middle of a string is pretty standard JavaScript coding. With ES2015, we now have a new way of doing this with template strings. Instead of using a single or double quote, you use the backtick character (this may take some searching on your keyboard, on my UK keyboard it is to the left of my 1 key). You then specify the dynamic values inside the expression with ${variable_name}.

function displayCount(count) {
    console.log(`I have ${count} animals`);
}

That looks nicer right? All the pluses and quotes get a little confusing sometimes, especially if you have multiple dynamic values in your string.


CLASSES

A fairly huge new feature is the introduction of the class keyword. If you have come to JavaScript from another object-oriented language, you will be very familiar with classes, if not, just understand that a class is just a tidy way of encapsulating your code. You will probably have been using a class hack without realising it.

Let’s see how we would have tried to write a “class” in ES5 syntax. It probably looks pretty familiar, we would just have created a function and then added methods to it by using its prototype object.

var Animal = function(name, age, colour) {
    this.name = name;
    this.age = age;
    this.colour = colour;
};

Animal.prototype.getDescription = function() {
    return this.name + ", " + this.age + " years old, " + this.colour;
};

But now it can look like this

class Animal {
    constructor(name, age, colour) {
        this.name = name;
        this.age = age;
        this.colour = colour;
    }

    getDescription() {
        return `${this.name}, ${this.age} years old, ${this.colour}`;
    }
}

You declare the constructor function with the constructor keyword. You can still use the this keyword to refer to the class. And you declare the class’ methods using the new method syntax without using the function keyword, just as I have done above.

You would then create an instance exactly as you would have done before

var bilby = new Animal("Brenda", 3, "grey");

SUBCLASSING

We can now also have one class inherit all the properties and methods of another. This is a great way of removing unnecessary duplicate code. The child class will then add its own custom behaviour on top of the parent’s.

So let’s see an example of subclassing using the new extends keyword. Here I have created a new Bilby class which inherits from the previously declared Animal class.

class Bilby extends Animal {
    constructor(name, age, colour) {
        super();
    }

    getDescription() {
        return `${super.getDescription()}, a Bilby`;
    }

    getLocation() {
        return "arid desert regions of Western Australia and the Northern Territory and a remote pocket in south-west Queensland";
    }

    calcBilbyAge() {
        return this.age * 13;
    }
}

You use the super keyword when you want to call a method in the parent class that you are overwriting in the child class. Here I am calling the Animal class’ constructor from the Bilby class’ constructor. I am also overwriting the getDescription method by appending some text to the returned value of the Animal class’ getDescription method.

All the non-overwritten variables and methods on the parent class are still accessible to the child class through the this keyword. The calcBilbyAge method is using this.age which is only declared in the Animal class.

Classes are a really neat and tidy way of organising your code, making it more flexible, extensible and manageable.


PROMISES

Promises are a great way of handling callbacks; if you have been using Angular at all you will probably be familiar with the $q service, but now we can write promises in pure JavaScript.

Let’s look at an example of some pre-ES2015 code where a promise might be beneficial. Here I am invoking a function which is going to make an HTTP request to a server, and then handling the success/failure of the request.

function getAnimal(animalUrl) {
    getData(animalUrl, function(response, error) {
        if (error) {
            console.log("Error: " + error);
        } else {
            displayData(response.data);
        }
    });
}

function getData(url, callback) {
    var request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.onload = function() {
        if (request.status >= 200 && request.status < 400) {
            callback.call(this, request.response);
        } else {
            callback.call(this, null, new Error("HTTP status: " + request.status));
        }
    };
    request.onerror = function() {
       callback.call(this, null, new Error("Request failed"));
    };
    request.send();
}

To utilise the new promise functionality we will need the getData function to return a promise. You can create a new promise using the new to ES2015 Promise constructor.

A promise initially exists in a pending state, and it can then either be resolved or rejected. A resolved promise will execute a success handler (if one has been provided) and a rejected promise will execute a fail handler.

function getData(url) {
    return new Promise(function(resolve, reject) {
        let request = new XMLHttpRequest();
        request.open("GET", url, true);
        request.onload = function() {
            if (request.status >= 200 && request.status < 400) {
                resolve(request.response);
            } else {
                reject(new Error(`HTTP status: ${request.status}`));
            }
        };
        request.onerror = function() {
            reject(new Error("Request failed"));
        };
        request.send();
    });
}

Then to use this new promise we would rewrite the getAnimal function to add a success handler with the then function and an error handler with the catch function.

function getAnimal(animalUrl) {
    getData(animalUrl)
        .then(function(response) {
            displayData(response.data);
        })
        .catch(function(error) {
            console.error(`Error: ${error}`);
        });
    });
}

This is a very simple example but you get the idea. Promises can provide a very nice way to work with asynchronous calls.


MODULES

Modules provide a new way of importing external libraries into your code without polluting the global namespace.

Let’s see how to create our own module – here is a simple (and not very useful) library for logging a message with an Australian animal-themed prefix.

var animals = ["bilby", "echidna", "platypus", "kookaburra", "potoroo"];

function logAnimalMsg(message) {
    var randomIdx = Math.floor(Math.random() * animals.length);
    console.log(`${animals[randomIdx]} ${message}`);
}

Now we will need to export the functions that we are wanting to use externally. We do this with the export keyword followed by an object containing the different methods we want to use.

var animals = ["bilby", "echidna", "platypus", "kookaburra", "potoroo"];

function logAnimalMsg(message) {
    var randomIdx = Math.floor(Math.random() * animals.length);
    console.log(`${animals[randomIdx]} ${message}`);
}

export { logAnimalMsg };

(This is an example of the new object initialisation syntax mentioned earlier in this post).

We will still need to load the JS file into our application, but doing so no longer adds the logAnimalMsg function onto the global namespace. To use it, we would need to import it into our source code by using the import keyword. You can import specific named functions like so

import { logAnimalMsg  } from "./animal-messages.js";

logAnimalMsg("my message");

Or an alternative way of importing is to import everything that is exported from a file and assign them all to an object.

import * as animalMessages from "./animal-messages.js";

animalMessages.logAnimalMsg("my message");

And it’s not only functions you can export/import, you can also do it with constants and classes, in just the same way.


And that’s it! Well, what I considered to be the most exciting anyway. If you want to read up more, there is a really good set of articles on Mozilla Hacks called ES6 in Depth. And if you want to have a more practical lesson, Code School has a good course called ES2015 – The Shape of JavaScript to Come. You may also want to do some research into Babel if you aren’t already familiar with it. Babel allows you to write ES2015 today and compiles it into a format that the browsers of today will be able to understand, as sadly it will be a few years before the browsers all catch up with this latest release.

JavaScript Test Coverage in Bamboo

At my work I was recently given the task of getting the test coverage of the unit tests in our JavaScript project to work with Atlassian’s CI server Bamboo. I had a bit of  a hard time finding information about how to do this, so I thought I would put it all down here.

For my project, we are writing our unit tests in Jasmine and running them with Karma. The information I found is framework-agnostic, but you will need to be using the Karma test runner to follow along.

To get your test coverage displaying in Bamboo you need to produce a Clover report. This is just an xml, and we can do this pretty easily.

So this comes in 2 steps – setting it up Karma-side and setting it up on Bamboo.

 


KARMA

If you aren’t currently using the Karma test runner but want to follow this post, you will need to first set it up. Follow the steps on their site, it is a fairly straightforward process.

The first step to getting the clover coverage report is to add the coverage reporter. I am using dots for the test output (this comes with Karma so you don’t need to install anything extra if you want to use it), and then I will use karma-coverage for the test coverage output. You will need to run in your console:

npm install karma-coverage --save-dev

Now you can edit the karma config file you are using for your project. Update the reporters array to include the coverage reporter.

reporters: ['dots', 'coverage']

Then add a new property coverageReporter

coverageReporter: {
    reporters: [
        {type: 'text-summary'},
        {type: 'clover', dir: 'test-reports', subdir: '.', file: 'clover.xml'}
    ]
}

There are several types of coverage reporters you can use here – text-summary will print the final coverage results in the console. You can also use one called text if you want a class by class analysis.

The clover reporter is the key one for integrating with Bamboo, as this is the format of test coverage Bamboo understands. This is for some reason missing on the documentation for karma-coverage, but it is there and you can use it without having to install anything extra.

One last thing you will need to do in your karma config file is add a preprocessor task for the coverage:

preprocessors: {
    'app/src/**/*.js': 'coverage'
}

Target all the source files you want to run the coverage on.

For reference, here is my final karma.conf.js file:

module.exports = function(config) {
    config.set({
        basePath: '',
        frameworks: ['jasmine'],
        files: [
            'js/app.js',
            'js/**/*.js',
            'test/**/mocks.js',
            'test/**/utils.js',
            'test/**/*.js'
        ],
        preprocessors: {
            'js/**/*.js': 'coverage'
        },
        reporters: ['dots', 'coverage'],
        coverageReporter: {
            reporters: [
                {type: 'text-summary'},
                {type: 'clover', dir: 'test-reports', subdir: '.', file: 'clover.xml'}
            ]
        },
        port: 9876,
        colors: true,
        logLevel: config.LOG_ERROR,
        autoWatch: true,
        browsers: [
            'PhantomJS'
        ],
        singleRun: false
    })
}

 


BAMBOO

You will need to have been given certain administrator rights to the project you want to set this up on to see the options I will mention. Or have access to someone with those rights who can help you for a few minutes 😉

First open the build plan

Then select Actions ▶ Configure Plan

bamboo plan

Select the job you want this on

bamboo job

If you haven’t already, add your tasks for running tests and parsing the results

bamboo tasks

Select the Miscellaneous tab – you should see a heading Would you like to view Clover Code Coverage for this plan?

Enable the checkbox Use Clover to collect Code Coverage for this build.

Then choose Clover is already integrated into this build and a clover.xml file will be produced

Specify the path to where your clover xml file is output – the one you specified in the karma config file.

clover setup

Now if you push your code and run the build plan, you should see a new tab Clover on your project page

You can use this to see your coverage, and track its progress over time – mine here is just a straight line but yours might be a bit more interesting after a few commits…

clover coverage example

And that’s it! Now you can use Bamboo to keep track of your code coverage and work towards getting that 100%

Happy testing!

e2e Testing With Protractor

End-to-end testing (or e2e testing) is testing from a user’s perspective. Rather than testing that a controller’s functions work as expected, it tests the whole of your app, things such as navigating through the pages, and if you click this link it loads the right page, if you type in the search box your results are filtered, etc.

When running e2e tests, you actually open a browser and simulate clicks and typing, and check your app has performed the desired result. In end-to-end tests, we don’t mock the interactions with the server (as you would in unit tests); we use the real server responses.

End-to-end tests are generally much slower to run than unit tests. But they are also different and test different things, and definitely have their place in your project.


Test Structure

e2e tests are structured around pages rather than specific controllers or services, etc. In theory, the entire structure of your app’s code could change, and the e2e tests would still work as long as the pages presented to the user were the same.

In our project we might have a test suite that is looking at the login page, testing the login functionality works when particular buttons are clicked and the correct webpage is loaded on a successful login. And we might have another test suite looking at a comments section, checking a user can input and submit a comment, with validation on their input, checking number of characters and sanitisation, etc.


Selenium & WebDriverJS

Protractor is built on top of WebDriverJS which uses native events and browser-specific drivers to interact with your application as a user would. Selenium provides the infrastructure for the W3C WebDriver specification.

It is helpful to remember that when you are having an issue getting something to work, that it may be more useful to you to look at the WebDriverJS/Selenium docs. Sometimes the Protractor docs aren’t really good enough, and as it is built on top of WebDriverJS, you can often find your problem really lies there.


Protractor

https://angular.github.io/protractor/#/

Protractor was created by the AngularJS team and is an end-to-end test framework for AngularJS applications. Protractor runs tests against your application running in a real browser, interacting with it as a user would.It has special locators for Angular-specific elements, and is built to be very asynchronous so it will automatically wait for the webpage to finish any pending tasks before running the next step in a test.

GETTING STARTED

To install Protractor, in the command line execute

npm install -g protractor

Then use the webdriver-manager helper tool which will now be available to you to get an instance of Selenium server running

webdriver-manager start
webdriver-manager update

If you want to run your tests in Internet Explorer then run

webdriver-manager update --ie

This will download an IE driver for you to use. There are problems with the 64 bit driver, most noticeable with sendKeys() – it takes about 10 seconds to enter one character and your test times out. Unfortunately the webdriver manager automatically detects your system and doesn’t give you the option to download the 32 bit driver instead. To get around this you can download the 32 but driver manually – download it here.

You set your configuration in a config file called protractor.conf.js

You can specifiy:

  • Which browsers to run and what versions
  • Where the web drivers are (these are the executables required by Selenium to load the browsers)
  • Where the test files are
  • A baseUrl to use in your tests – this makes it easy to change the URL of the site it is loading between local, dev, prod, etc.

See the full list of configuration options here

As an example, here is my config file, I am executing my tests in Chrome, IE and Firefox

protractor.conf.js

exports.config = {
   seleniumServerJar: "./node_modules/protractor/selenium/selenium-server-standalone-2.45.0.jar",
   chromeDriver: "./node_modules/protractor/selenium/chromedriver.exe",
   seleniumArgs: ["-Dwebdriver.ie.driver=node_modules/protractor/selenium/IEDriverServer.exe"],
   multiCapabilities: [
      { browserName: "firefox" },
      { browserName: "chrome" }
      { browserName: "internet explorer" }
   ],
   specs: ["test/e2e/**/*E2E.js "],
   baseUrl: "http://localhost:8383/",
   jasmineNodeOpts: {
      showColors: true,
      defaultTimeoutInterval: 30000
   }
};

RUNNING TESTS

You can run the tests from the command line by executing

protractor protractor.conf.js

BROWSER

https://angular.github.io/protractor/#/api?view=Protractor

This is a property provided by Protractor with several useful variables/methods

  • browser.baseUrl – baseUrl value specified in config file
  • browser.get() – used to load a webpage
  • browser.wait() – pause execution until something is true, returns a promise
  • browser.sleep() – pause execution for a specified length of time, returns a promise
  • browser.getCurrentUrl()

LOCATORS

You can locate elements on the webpage using several different techniques which fall under either:

  • CSS
  • HTML
  • Angular-specific

Locators are passed to the element function, which will find and return elements in a page using the locator. Locators are called with by.{locator type}({criteria})

Here are some examples of the different ways you can select elements on the page.

// CSS locators
element(by.css(".anyClass"));
element(by.css("#anyID"));
element(by.css("div.myDivClass"));
element(by.css("ul > li"));
element(by.css("button[type=submit]"));

// HTML locators
element(by.buttonText("click"));
element(by.tagName("ul"));
element(by.name("anyName"));

// Angular locators
element.all(by.repeater("item in list"));
element(by.binding("person.name"));
element(by.model("person.name"));

The element function returns an object you can use in your tests, and provides helpful methods for making asserts on elements such as isPresent() and isDisplayed(). There also methods for interacting with items like click() and sendKeys().

So now we have covered the general basics, let’s have a look at what some tests can look like. I am using Jasmine to write my tests.

describe("MyPage", function() {

    beforeEach(function() {
        browser.get("/"); // loads baseUrl in browser
    });

    it("should have a submit button", function() {
        var submitBtn = element(by.css("button[type=submit]"));
        expect(submitBtn.isDisplayed()).toBeTruthy();
    });

    it("should change URL on button click", function() {
        var submitBtn = element(by.css("button[type=submit]"));
        submitBtn.click();
        expect(browser.getCurrentUrl()).toEqual("http://kumikoro.test.com/submit");
    });

    it("should set text of input", function() {
        var input = element(by.name("textInput"));
        input.sendKeys("ratchet");
        expect(input.getText()).toEqual("ratchet");
    });
});

PROMISES

You can create promises in Protractor, very similar to the $q service in Angular, just a slightly different syntax.

function getPromise() {
    var deferred = protractor.promise.defer();
    if (promiseSuccess) {
        deferred.fulfill(true);
    } else {
        deferred.reject("error");
    }
    return deferred.promise;
}

EXPECTED CONDITIONS

https://angular.github.io/protractor/#/api?view=ExpectedConditions

As in e2e tests you are loading a webpage, you often need to wait for elements to be resolved, and the webpage to fully load before you can execute your tests. Protractor provides the browser.wait method which will pause the test until a condition is true. You can give it an ExpectedCondition, a promise or a custom function.

protractor.ExpectedConditions has several methods which check things such as presence of an element, if an element is clickable, if an element contains certain text…

var EC = protractor.ExpectedConditions;

// test will hold until Protractor can find this element
// it will timeout and fail the test if it still cannot find the
// element after 10000ms
browser.wait(EC.presenceOf(element(by.css(".nav"))), 10000);

// test will hold until Protractor can find the text 'OK' in the
// body tag, when it does it will run the promise success handler
// if it fails it runs the error handler
// again test timeouts after 10000ms if it can't find 'OK' text
browser.wait(EC.textToBePresentInElement(element(by.tagName("body")), "OK"), 10000)
    .then(function(){
        // success
    }, function(error) {
        // failed...
    });

Let’s see an example that combines both Promises and Expected Conditions. Let’s say I am testing my login page. I want to log out of my site before starting any of my tests so each test starts fresh. I want to wait until the logout is successful before running anything – here is where a promise would help.

function logout() {
   var deferred = protractor.promise.defer();

   browser.get("#/logout");

   browser.wait(EC.textToBePresentInElement(element(by.css("body")), "OK"), 10000).then(function() {
      deferred.fulfill(true);
   }, function(error) {
      deferred.reject(error);
   });

   return deferred.promise;
};

beforeEach(function() {
   logout().then(function() {
      browser.get("#/login");
   });
});

You can see here I am loading a logout URL, and waiting for its body to contain the text ‘OK’, indicating the logout was successful. Then I load the login page and continue with my test.


Page Objects

Page Objects are a design pattern that is recommended by Selenium for using with e2e tests. Page Objects abstract the interaction between the browser and your tests, resulting in cleaner tests. All references to Protractor’s methods such as element or browser should be inside a Page Object, not in your test class

USAGE

To create a Page Object, just create a JavaScript class and then assign its value to module.exports.Then in your test you can use require to load in the Page Object. Protractor uses NodeJS to load in the Page Object and all its functions are then available to you.

Here is a simple example:

var LoginPage = (function() {

    this.loadLoginPage = function() {
        browser.get("#/login");
    };
});
module.exports = new LoginPage();
describe("login", function() {
    var LoginPage = require("./pageObjects/loginPage.js");

    beforeEach(function() {
        LoginPage.loadLoginPage();
    });

    /** tests go here **/
});

Debugging

Debugging your e2e tests can be a little bit weird, or maybe I am just not used to it yet. Protractor provide some methods on the browser object you can use to help you work out a problem.

Use browser.pause() in your test when you want a pause – you can then use the debug tools in the browser to inspect what is going on.

Use browser.debugger() where you want to break, which is essentially adding a breakpoint that your browser will hit. You will need to change the protractor config to run in debug mode for this to work.


To Finish

Here are some articles I found helpful when getting started with Protractor and e2e testing:

And I found both these books to be very helpful

Getting Started With Unit Testing With AngularJS

Nowadays everyone talks about unit tests and TDD, and we all know the benefits of incorporating tests into a project. One of Angular’s strengths is that it is very testable. This article will cover how to get started unit testing your Angular project, and look at how we can test controllers, services & directives.

I will use the Jasmine BDD framework for writing my tests, you may have a different preference such as Mocha, go ahead and use whichever you prefer. I am also using the karma test runner.


ngMock

ngMock is an Angular module you can include in your app that allows you to inject and mock Angular services into unit tests. It also extends various core Angular services (like $timeout) to make testing easier, and provides new ones like $httpBackend which can be used to fake a response from the server.

ngMock publishes 2 functions on the window for easy access – module and inject.

Use module to load an Angular module into your test – you will always need to load the module that the controller/service/directive you are testing belongs to, there may be occasions where you want to load other modules as well.

Use inject to get the services (yours or Angular’s) that you need for your tests.

So let’s see an example that uses module and inject

angular.module("myApp", [])
    .factory("MyService", function() {
        // some awesome factory stuff
    });
describe("MyService", function() {
    var MyService,
        $httpBackend;

    beforeEach(module("myApp"));

    beforeEach(inject(function(_MyService_, _$httpBackend_, $timeout)   {
        MyService = _MyService_;
        $httpBackend = _$httpBackend_;
        // do something with $timeout...
    }));

    it("should test something", function() {
        var myVar = true;
        expect(myVar).toEqual(true);
    });
});

So here you can see I start by loading the module myApp. Then I inject 3 services into the test MyService, $httpBackend & $timeout. You may be wondering… what are those underscores doing? Angular gives you the option of wrapping injected services in underscores this way. This is only so you can save them to a variable with the correct name, like I have for MyService & $httpBackend. You don’t have to wrap the name in underscores, here I haven’t for the $timeout service – there isn’t really any point if you aren’t saving it to a variable.

Keep in mind that you need to load all your modules before you inject anything, or you will get an error along the lines of:

Error: Injector already created, can not register a module!

You can also use the module method to provide any needed values through Angular’s $provide service. If you have any values declared using a deferred bootstrapper, or values defined by a resolve block like in the ui-router module’s $stateProvider.

beforeEach(module(function($provide) {
    $provide.constant("CONFIG", getConfig());
    $provide.value("myResolvedValue", []);
}));

Testing a Service

I use the term service here to refer to any components created using module.factory, module.provider or module.service.

They are a good place to start adding tests as they are pretty simple and have few dependencies, and the ones they do have are easily mocked. So, let’s get started! Here is an example of a simple factory with a method for adding 2 numbers together.

angular.module("myApp", [])
    .factory("AddFactory", function() {
        function add(n1, n2) {
            return n1 + n2;
        }
        return {
            add: add
        };
    });

And then to write the test you inject the service into the test (something we have already done) and then make asserts on its methods. Easy 🙂

describe("AddFactory", function() {

    var AddFactory;

    beforeEach(module("myApp"));

    beforeEach(inject(function(_AddFactory_) {
        AddFactory = _AddFactory_;
    }));

    it("should add 2 numbers together", function() {
        var result = AddFactory.add(2, 3);
        expect(result).toEqual(5);
    });
});

And those are the basics of testing a service. It’s pretty simple really, once you get your head around the syntax.

Services with Dependencies

If you have a service which uses other services and you want to mock these dependencies, you can use $provide to inject the mocked values in – make sure to do this after the module has been loaded, or the value loaded from the module will overwrite the mocked value.

Mocking a service this way helps to isolate the service so we know we are testing its functions, not its dependecies’.

So as an example, let’s look at the AddFactory again, but this time give it a dependency on another service CalculatorFactory.

angular.module("myApp", [])
    .factory("AddFactory", function(CalculatorFactory) {
        function add(n1, n2) {
            return CalculatorFactory.add(n1, n2);
        }
        return {
            add: add
        };
    });
describe("AddFactory", function() {

    var AddFactory,
        CalculatorFactory;

    beforeEach(module("myApp"));

    // providing a mocked value for CalculatorFactory after myApp 
    // module has loaded
    beforeEach(module(function($provide) {
        CalculatorFactory = function() {
            return {
                add: function(a, b) { return a + b; }
            };
        };
        $provide.factory("CalculatorFactory", CalculatorFactory);
    }));

    beforeEach(inject(function(_AddFactory_) {
        AddFactory = _AddFactory_;
        // AddFactory is now using the mocked value for 
        // CalculatorFactory
    }));

    it("should add 2 numbers together", function() {
        var result = AddFactory.add(2, 3);
        expect(result).toEqual(5);
    });
});

$httpBackend

Angular’s $httpBackend service can be used to fake a server response, so we can test how our service (or controller or directive…) handles different responses. It can respond with any value and also HTTP error codes. This means our unit tests can run quickly with no external dependencies.

Here is a brief summary of the different methods it provides:

$httpBackend.whenGET/POST/PUT/DELETE
Tell it what to do when a specified URL is called with the corresponding HTTP method

$httpBackend.expectGET/POST/PUT/DELETE
Expectation that is checking a specified URL was called with the corresponding HTTP method

$httpBackend.flush()
Needs to be called to flush the pending requests

$httpBackend.verifyNoOutstandingExpectation()
$httpBackend.verifyNoOutstandingRequest()

Put in afterEach block (tear-down) for every test that uses $httpBackend

And as an example, let’s test a service, where we expect it to make a HTTP POST request when a particular method is called.

angular.module("myApp", [])
    .factory("MyService", function($http) {
        function save(params) {
            $http.post("http://kumikoro.test.com", params);
        }
        return {
            save: save
        };
    });
describe("MyService", function() {
    var MyService,
        $httpBackend;

    beforeEach(module("myApp"));

    beforeEach(inject(function(_MyService_, _$httpBackend_) {
        MyService = _MyService_;
        $httpBackend = _$httpBackend_;
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    it("should make POST request when call save", function() {
        $httpBackend.whenPOST("http://kumikoro.test.com").respond();
        $httpBackend.expectPOST("http://kumikoro.test.com");
        MyService.post({name: "ratchet"});
        $httpBackend.flush();
    });
});

So here you can see a test which is verifying that the expected POST request was made to the URL when the service’s save method was called. Notice how I call $httpBackend.flush() at the end. This is very important and your test won’t work without it. Angular queues the HTTP responses and waits for you to tell it when to send them. This can be very helpful in your tests, but it is a common mistake to forget to flush the queue – something to keep in mind!

The whenPOST method is saying the $httpBackend should send an empty response when a POST request is sent to http://kumikoro.test.com. You can respond with data or HTTP status codes (to simulate errors) as well. The expectPOST method is the assert in this test, if no POST request was made the $httpBackend service will throw an error when it is flushed.

// responding with data
$httpBackend.whenPOST("http://kumikoro.test.com").respond({id: 1});
// responding with 404 error
$httpBackend.whenPOST("http://kumikoro.test.com").respond(404);

Testing a Directive

Angular directives are composed of a template html file (most of the time) and JavaScript. To test a directive we need to load the template into Angular’s $templateCache so it can be compiled correctly.

If you are using karma like me then we can use the karma-ng-html2js-preprocessor karma plugin to do this.

In the command line, execute

npm install karma-ng-html2js-preprocessor --save-dev

And then update your karma config file to use the preprocessor for the template html files

...
    preprocessors: {
      "templates/**.html": ["ng-html2js"]
    },
    ngHtml2JsPreprocessor: {},
...

There are a lot of options you can put inside the preprocessor, see their github page for the docs.

We can then load the template html as a module into the test.

beforeEach(module("templates/header.html"));

Compiling a Directive

The first step to testing a directive is to compile it

  1. Create the element using angular.element passing in the html you would use to create your directive
  2. Then create a new scope with $rootScope.$new()
  3. Use $compile to compile the element with the passed in scope
  4. Then call $scope.$digest() to fake the natural lifecycle of a directive
describe("MyDirective", function() {
    var scope,
        element;

    beforeEach(module("templates/directive.html"));
    beforeEach(module("myApp"));

    beforeEach(inject(function($rootScope, $compile) {
        element = angular.element("<my-directive></my-directive>");
        scope = $rootScope.$new();
        $compile(element)(scope);
        scope.$digest();
    }));
});

Directives with Attributes

If your directive needs values passed to it as html attributes, you can do this by assigning them to the scope before compiling the directive.

beforeEach(inject(function($rootScope, $compile) {
    element = angular.element("<my-directive items='myItems'></my-directive>");
    scope = $rootScope.$new();
    scope.myItems = ["bilby", "quokka", "wombat"];
    $compile(element)(scope);
    scope.$digest();
}));

Tests

You can then make asserts on the scope or the element

it("should display 'CLICK' as button text", function() {
    var btnText = element.find("button").text();
    expect(btnText).toEqual("CLICK");
});

it("should call scope.onItemClick() when item in menu is clicked", function() {
    spyOn(scope, "onItemClick");
    var listItem = element.find("ul").find("li").eq(1);
    listItem.triggerHandler("click");
    expect(scope.onItemClick).toHaveBeenCalled();
});

Testing a Controller

Compiling the Controller

When testing a controller, you generally make asserts against the scope. We will pass a mocked scope into the controller’s constructor so we can then run our tests on it.

  1. Create a new scope using $rootScope.$new()
  2. Then create the controller using Angular’s $controller service
describe("MyController", function() {
    var MyController,
        scope;

    beforeEach(module("myApp"));

    beforeEach(inject(function($rootScope, $controller) {
        scope = $rootScope.$new();
        MyController = $controller("MyController", {
            $scope: scope
        });
    }));
});

You can inject any other services that you want to mock this way too, so you can spy on method calls, etc.

describe("MyController", function() {
    var MyController,
        scope,
        AddFactory;

    beforeEach(module("myApp"));

    beforeEach(inject(function($rootScope, $controller, $window) {
        scope = $rootScope.$new();
        AddFactory = {
            add: function(){}
        };
        MyController = $controller("MyController", {
            $scope: scope,
            $window: $window,
            AddFactory: AddFactory
        });
    }));

    it("should close window when function called", function() {
        spyOn($window, "close");
        scope.myControllerFunction();
        expect($window.close).toHaveBeenCalled();
    });
});

Scope Inheritance

Some controllers inherit their scope from another controller, and need access to the variables and methods on their parent’s scope. Rather than mocking it out for every function in the parent scope, we can create a scope based off the parent controller’s.

  1. Create a new scope with $rootScope.$new()
  2. Create the parent controller using $controller, passing in this scope
  3. Then call scope.$new() on this scope instance – this will create a new child scope
  4. Create the controller you want to test passing in the new child scope
<div ng-controller="ParentController">
    <div ng-controller="ChildController"></div>
</div>
angular.module("myApp")
    .controller("ParentController", function($scope) {
        $scope.bilby = "brenda";
    })
    .controller("ChildController", function($scope, $log) {
        $scope.logBilby = function() {
            $log.log($scope.bilby);
        };
    });
describe("ChildController", function() {
    var ChildController,
        parentScope,
        scope,
        $log;

    beforeEach(module("myApp"));

    beforeEach(inject(function($rootScope, $controller, _$log_) {
        $log = _$log_;

        parentScope = $rootScope.$new();
        $controller("ParentController", {
            $scope: parentScope
        });

        scope = parentScope.$new();
        ChildController = $controller("ChildController", {
            $scope: scope,
            $log: $log
        });
    }));

    it("should log 'brenda'", function() {
        scope.logBilby();
        expect($log.log.logs).toContain("brenda");
    });
});

Resolving Promises

You may want to test a function in your controller that is calling a function that returns a promise.

To do this, we can mock the service as mentioned previously, and then create and resolve/reject a fake promise object with the $q service. We then need to call $scope.$apply() which will cause the promise’s success/fail handler to run. (I have found it is often helpful to call $scope.$apply() after creating a controller as it may have promises that need resolving in its initialisation.)

As an example, let’s look at a controller with a method to open a modal dialog. The $modal.open() function returns a promise, and if it has opened successfully the controller sets a property on the scope.

angular.module("myApp")
    .controller("MyController", function($scope, $modal) {
        $scope.opened = false;
        $scope.openModal = function() {
            $modal.open().then(function() {
                $scope.opened = true;
            });
        };
    });

And now here is the test that checks this property is set correctly when the modal dialog opens successfully. We mock the $modal service, and use the $q service to mock the promise.

describe("ChildController", function() {
    var MyController,
        scope,
        $modal;

    beforeEach(module("myApp"));

    beforeEach(inject(function($rootScope, $controller, $q) {
        scope = $rootScope.$new();
        $modal = {
            open: function() {
                var deferred = $q.defer();
                deferred.resolve("my data"); // could also reject
                return deferred.promise;
            }
        };

        MyController = $controller("MyController", {
            $scope: scope,
            $modal: $modal
        });
    }));

    it("should set opened to true when modal dialog opens", function() {
        scope.openModal();
        scope.$apply(); // this will cause the promise's success 
                        // handler to run
        expect(scope.opened).toEqual(true);
    });
});

To Finish

And that pretty much covers the basics of getting started with testing in AngularJS. As you can see, the Angular team have really made it easy to find the seams to inject your mock data into. After you get used to the strange syntax, it becomes easy to understand, and quick and easy to write the tests you need to ensure the stability and reliability of your project.

I hope you found this article helpful, and Happy Testing! 🙂

if you’d like to do some further reading, here are some links I found helpful when I first got started with my AngularJS tests:

And I found both these books to be very helpful

Using Gulp To Build & Run A JavaScript Project

Gulp is a very powerful tool that can be used to help build and deploy our JavaScript projects (amongst many other things). The benefit of using Gulp, or a similar tool such as Grunt, is that with a press of a button your project can run its tests, minify the JavaScript files, compile the SASS, compress images, and then open up a browser window with your project running for you to play with. And it does all this in a way which will just work on any computer, Mac or PC, whichever IDE you choose to develop with.

I recently decided to have a play around with Gulp and build my portfolio website using it. I had a bit of trouble finding a good list of all the tasks which I felt I needed to build and run my website, and so decided to list them here in one spot in case this helps anyone else.

I’ll go through them step by step in this post, but if you just want to skip to my gulpfile, you can view it on my github page.


GETTING STARTED

If you haven’t already, you will need to get Gulp up and running on your machine (if you have already done this go ahead and skip to the next section). To get Gulp running, you will need to install node, so as to have access to npm (node package manager) in the command line.

Go to the node website and click on the ‘INSTALL’ link, and run the file once it has downloaded. In the Custom Setup screen, make sure to select the ‘Add to PATH’ option so you will be able to use npm in the command line. If you have installed node and forgot to select this, it is probably easier to just uninstall node and start again, it doesn’t take much time. Once it is installed, you may need to restart your computer. You can test node has installed correctly by opening a command window and executing

npm -v

which should print out the current version of npm you are using.

Now you need to create a file called package.json and save it to your project’s root directory. This will hold the information about all the dependencies installed through node. Here is a sample file you can copy and change the values of:

{
  "name": "Heather-Roberts-site",
  "version": "1.3.0"
}

You can now install Gulp and save it to your package.json by opening a command window in your project’s root directory and running

npm install --global --save-dev gulp

You should see a new folder in your project called node_modules which contains a folder called gulp. Back in the command line, try running

gulp

It will probably give you an error along the lines of ‘Cannot locate gulpfile’ but it should recognise the command.

The global flag we used means you can use the gulp command from any location on your computer not just this directory where you’ve installed it. And save-dev adds Gulp into your package.json file with the version required by your project.

Now you need to create your gulpfile.js – put this with your package.json file in your project root, and for now just populate it with

var gulp = require("gulp");

gulp.task("default", function() {});

You should now be able to execute

gulp

from the command line and see it run without errors. However, nothing will happen as we are not actually telling it to do anything just yet. Now we need to start adding our tasks!

You should be able to find all of this information on the gulp site – if you are have any issues getting started, you should be able to get help there.


TASKS

JSHINT
gulp-jshint

A good thing to do before deploying your code is to check its quality, and make sure there aren’t any syntax errors, etc. JSHint can give our code a once over to make sure of its standard, and we can add a Gulp task for this which will output any issues in the command window.

So let’s write our very first task. First we need to install the JSHint package and save it to our project dependencies. So run

npm install gulp-jshint --save-dev

If you open package.json you should now see an entry for gulp-jshint with its corresponding version number. And now in the gulpfile we need to import the plugin.

var gulp = require("gulp");
var jshint = require("gulp-jshint");

gulp.task('default', function() {});

Node is using the require function here to go and load the gulp-jshint package that you should be able to see has been added into your node_modules directory.

Now we create our new lint task

var gulp = require("gulp");
var jshint = require("gulp-jshint");

gulp.task("lint", function() {
 return gulp.src("js/**.js")
  .pipe(jshint())
  .pipe(jshint.reporter("default"));
 });

gulp.task("default", function() {});

The value passed to gulp.src() is the file pattern to run the task on. Gulp lets you specifiy a String or an Array of explicitly names files ie. “js/app.js” or [“js/app.js”, “js/init.js”]. Or you can use what they call a glob which is what I have done here with the double stars in “js/**.js”. Here we want to look at any JS file in the js folder. There are several different options you can use, to see the full range look at the node-glob docs.

The pipe() function is just adding on the functionality you want to run on that selection of source files. So we are running jshint() and then adding a reporter for JSHint to use. The reporter is just the way the results are output, there are a few values you can use, check the JSHint docs if you aren’t satisfied with the default one I have selected.

Now if you run

gulp

in the command line, still nothing happens. That’s because we need to either add lint to the default task or explicitly call the lint task.

gulp lint

Now you should see something running, and maybe you will have some warnings or errors from JSHint, or maybe your code passes through error free.

To add lint to the default task, we just pass an Array into the default task containing it.

var gulp = require("gulp");
var jshint = require("gulp-jshint");

gulp.task("lint", function() {
 return gulp.src("js/**.js")
  .pipe(jshint())
  .pipe(jshint.reporter("default"));
 });

gulp.task("default", ["lint"]);

The default task is what is run if you just execute

gulp

in the command line. You can group tasks in Gulp, which is another of its strengths, and add several tasks to the default one. Or you can create a custom task group such as build or deploy, and then add this into the default task or run it explicitly from the command line.

CONCAT
gulp-concat

The next group of tasks will look at what we can do to our JavaScript files. A pretty standard thing to do is to concatenate all the project’s JS files into one file. To do this I will use a node package called gulp-concat.

So, first run the node install

npm install gulp-concat --save-dev

And import it into the gulpfile

var gulp = require("gulp");
var jshint = require("gulp-jshint");
var concat = require("gulp-concat");

And write a new task called scripts, which we’ll add to the default task after lint

...
gulp.task("scripts", function() {
 return gulp.src("js/**.js")
  .pipe(concat("app.js"));
 });

gulp.task("default", ["lint", "scripts"]);

If you run

gulp

now, you should see all the script files are concatenated into a new file called app.js.

MINIFY
gulp-uglify

To minify the JavaScript I will use the gulp-uglify package.

npm install gulp-uglify --save-dev

Update the gulpfile like so

var gulp = require("gulp");
var jshint = require("gulp-jshint");
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
...
gulp.task("scripts", function() {
 return gulp.src("js/**.js")
  .pipe(concat("app.js"))
  .pipe(uglify());
 });
...

This will now copy all scripts into a new file called app.js and then minify it.

On a side note – if you are using Angular JS and now try to load your project using the new app.js file, you will probably find your application throws some errors. This is because the JS files have been compressed too much for Angular to work. To fix this issue, update the uglify call like so

...
gulp.task("scripts", function() {
 return gulp.src("js/**.js")
  .pipe(concat("app.js"))
  .pipe(uglify({mangle: false}));
 });
...

And your application should now run error-free again.

RENAME
gulp-rename

Now our file has been minified, it would be nice to rename it to reflect this by appending the suffix .min

npm install gulp-rename --save-dev
var gulp = require("gulp");
var jshint = require("gulp-jshint");
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
var rename = require("gulp-rename");
...
gulp.task("scripts", function() {
 return gulp.src("js/**.js")
  .pipe(concat("app.js"))
  .pipe(uglify())
  .pipe(rename({suffix: ".min"}));
 });
...

If you test running

gulp

you should see you now get a file called app.min.js which contains all your minified JavaScript files.

STRIP DEBUG STATEMENTS
gulp-strip-debug

Another helpful task is one that will remove any console.log() .warn() .error() calls and any alert() popups that you’ve put in to help you debug in development.

npm install gulp-strip-debug --save-dev
var gulp = require("gulp");
var jshint = require("gulp-jshint");
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
var rename = require("gulp-rename");
var stripDebug = require("gulp-strip-debug");
...
gulp.task("scripts", function() {
 return gulp.src("js/**.js")
  .pipe(stripDebug())
  .pipe(concat("app.js"))
  .pipe(uglify())
  .pipe(rename({suffix: ".min"}));
 });
...

I have called stripDebug() before the other script tasks as it makes sense to remove the debug statements, making the files smaller, before running the other processes. It is good to think about the order you do your tasks in, and what is the most efficient way.

COPY

It is a pretty standard practise to move all the files needed to run the project into their own directory. It is common to call this folder app or www or dist. I will call mine www, but whatever you like is fine.

To copy files over we do not need to install any new packages as this comes part and parcel with Gulp through the dest() function.

...
gulp.task("scripts", function() {
 return gulp.src("js/**.js")
  .pipe(stripDebug())
  .pipe(concat("app.js"))
  .pipe(uglify())
  .pipe(rename({suffix: ".min"})
  .pipe(gulp.dest("www/js"));
 });
...

This will move app.min.js into a new directory called www/js. Gulp will handle creating this directory if it doesn’t exist already.

As you can see, we have grouped several different Gulp modules into one very powerful task which we can execute at the click of a button, saving us a huge amount of time.

MINIFY HTML
gulp-htmlmin

Now I’ll add a task to minify the HTML, which needs a different node package than the one we used to minify the JS files. We’ll write a new Gulp task which will handle minifying the HTML files and moving them to the new www directory.

npm install gulp-htmlmin --save-dev
var gulp = require("gulp");
var jshint = require("gulp-jshint");
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
var rename = require("gulp-rename");
var stripDebug = require("gulp-strip-debug");
var htmlmin = require("gulp-htmlmin");
...
gulp.task("html", function() {
 return gulp.src("index.html")
  .pipe(htmlmin({collapseWhitespace: true}))
  .pipe(gulp.dest("www"));
});
...

And remember to add it to the default task

...
gulp.task("default", ["lint", "scripts", "html"]);

Now execute

gulp

And you should see index.html turn up in the www directory, minified. Make sure to update the file pattern here to target all your HTML files, I have only done index.html for ease of demonstrating.

SASS
gulp-sass

The next thing we will look at is compiling SASS. This will not apply to everyone, some people use LESS, or no preprocessor at all. If SASS isn’t you, you might want to skip to the next section.

So we need a task that will compile the SASS into CSS, compress the CSS, rename the file with the .min suffix and move it into our new www folder. The only new package we need to install is one called gulp-sass which will handle the SASS compilation and compressing the CSS.

npm install gulp-sass --save-dev
var gulp = require("gulp");
var jshint = require("gulp-jshint");
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
var rename = require("gulp-rename");
var stripDebug = require("gulp-strip-debug");
var htmlmin = require("gulp-htmlmin");
var sass = require("gulp-sass");
...
gulp.task("sass", function() {
 return gulp.src("css/app.scss")
  .pipe(sass({outputStyle: "compressed"}))
  .pipe(rename({suffix: ".min"})
  .pipe(gulp.dest("www/css"));
 });
...

And again, update the default task

...
gulp.task("default", ["lint", "scripts", "html", "sass"]);

I initially started using a different sass module called gulp-ruby-sass as I read another tutorial recommending it as it has more features than gulp-sass, but I ran into issues with my Angular work again – gulp-ruby-sass was trying to be clever and strip away the CSS that wasn’t being referenced in any HTML, but it wasn’t taking into account directive templates, so any classes in my custom directive templates were not being applied and my site looked broken. I had to switch to the gulp-sass task as I couldn’t see any way to switch off the CSS stripping. Just a heads up in case you come across a similar issue.

NEWER
gulp-newer

Now I’m going to look at copying asset files across to the new www directory. Often you can have a lot of assets and you don’t want to re-copy them across each time, so you can use gulp-newer to only copy those which are newer or aren’t in the destination directory.

npm install gulp-newer --save-dev
var gulp = require("gulp");
var jshint = require("gulp-jshint");
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
var rename = require("gulp-rename");
var stripDebug = require("gulp-strip-debug");
var htmlmin = require("gulp-htmlmin");
var sass = require("gulp-sass");
var newer = require("gulp-newer");

I want to copy image assets and font assets over, so to start with I’ll write 2 tasks to do so, and group them under one copy-assets task to add into the default task.

...
gulp.task("copy-imgs", function() {
 return gulp.src("assets/imgs/**")
  .pipe(newer("www/assets/imgs"))
  .pipe(gulp.dest("www/assets/imgs"));
 });

gulp.task("copy-fonts", function() {
 return gulp.src("assets/fonts/**")
  .pipe(newer("www/assets/fonts"))
  .pipe(gulp.dest("www/assets/fonts"));
 });

gulp.task("copy-assets", ["copy-imgs", "copy-fonts"]);
gulp.task("default", ["lint", "scripts", "html", "sass", "copy-assets"]);

This works fine, however it is obviously not great to write a new task that is doing pretty much exactly the same thing just to a different folder.

So I’ll rewrite this into one task that targets both directories.

...
gulp.task("copy-assets", function() {
 return gulp.src(["assets/imgs/**", "assets/fonts/**"])
  .pipe(newer("www/assets"))
  .pipe(gulp.dest("www/assets"));
 });

gulp.task("default", ["lint", "scripts", "html", "sass", "copy-assets"]);

Written like this though, it will just put all our files directly into the www/assets folder, we will lose the img and fonts folders. To preserve the original folder structure we can use the base option of gulp.src(). This option defines the base folder, and will mean your files are copied through in a way that preserves their folder structure.

...
gulp.task("copy-assets", function() {
 return gulp.src(["assets/imgs/**", "assets/fonts/**"], {base: "assets"})
  .pipe(newer("www/assets"))
  .pipe(gulp.dest("www/assets"));
 });

gulp.task("default", ["lint", "scripts", "html", "sass", "copy-assets"]);

WATCH

A very cool feature of Gulp is that it can watch the files you are working on and re-execute a task whenever something changes. So, for example, you can update one of your SASS files and Gulp will automatically re-compile and minify the CSS and copy it into the www directory without you having to do a thing. Watch is something inbuilt into the gulp module like copying files, so you don’t need to import anything new. Let’s add a new task called watch to run the sass task in the aforementioned circumstance.

...
gulp.task("watch", function() {
 gulp.watch("css/**.scss", ["sass"]);
});
...

The first parameter is just like the src() function, where you specify the file pattern to match using a String, a glob or an Array. If you now run

gulp watch

in the command line, and then go and change one of your SASS files, you should see the sass task gets executed again.

Now let’s update the watch task to run all the tasks written so far when their corresponding files change, and put it in the default task.

...
gulp.task("watch", function() {
 gulp.watch("css/**.scss", ["sass"]);
 gulp.watch("js/**.js", ["lint", "scripts"]);
 gulp.watch("index.html", ["html"]);
 gulp.watch(["assets/imgs/**", "assets/fonts/**"], ["copy-assets"]);
});

gulp.task("default", ["lint", "scripts", "html", "sass", "copy-assets", "watch"]);

CONNECT
gulp-connect-multi

The final task I will show you will load the project in a browser so you can actually view it after all the wonderful things you have done to it. This also has a live reload option, where you can set it up so that when you make a change to one of your files and its watch task runs and compiles/moves something etc. the browser will detect something has changed and reload the content.

npm install gulp-multi-connect --save-dev

When importing this into your gulpfile, it has a slightly different syntax in that you assign the execution to your variable by putting parentheses at the end

var gulp = require("gulp");
var jshint = require("gulp-jshint");
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
var rename = require("gulp-rename");
var stripDebug = require("gulp-strip-debug");
var htmlmin = require("gulp-htmlmin");
var newer = require("gulp-newer");
var connect = require("gulp-multi-connect")();
...
gulp.task("connect", connect.server({
 root: ["www"],
 port: 1337,
 livereload: true,
 open: {
  browser: "chrome" // if not working OS X browser: "Google Chrome"
 }
}));
...

Make sure to set the value of root to your destination directory. Now try running

gulp connect

and you should see your project load in a new tab in Google Chrome. If it isn’t loading, maybe have a look at the settings of gulp-connect-multi and specifiy a different browser. Failing that you can just type http://localhost:1337 into your browser.

To get the live reload functionality working you will need to update the previously written tasks by adding .pipe(connect()); at the end. For example here is my sass task updated:

...
gulp.task("sass", function() {
 return gulp.src("css/app.scss")
  .pipe(sass({outputStyle: "compressed"}))
  .pipe(rename({suffix: ".min"}))
  .pipe(gulp.dest("www/css"))
  .pipe(connect.reload());
});
...

You might not want to always run the connect task in with everything else, so I’ll leave it up to you if you want to put it in the default task.


TO FINISH

So this is pretty much everything I have used on my own site, but every project is different and I have likely missed out something you need.

Some other tasks which you might be interested in are:

  • gulp-clean which you can use to empty out your destination directory
  • karma which you can use to execute your tests
  • gulp-imagemin which will compress any images

There are pretty much Gulp tasks available for everything you can think of, and you can easily extend the gulpfile I’ve built here to suit you and your projects.

When structuring your gulpfile, it is a good idea to think about the automation process a bit. It is more helpful to you for the tasks which are more likely to fail to run first, so you don’t have to sit through all the other tasks running only to have the whole thing fail at the final step. So, for example, it is a good idea to run any tests as one of the first steps.

So, that’s it! Have fun with Gulp 🙂

If you want to look at my whole gulpfile.js and the project it is running for, you can view it on my github page

Object-Oriented JavaScript

I came to JavaScript from ActionScript 3.0, as it became apparent that my much loved language was dying and I needed to make the transition to the ever more popular HTML5. When I first encountered JavaScript, my biggest problem with it was that it seemed so unstructured and… casual. There is no variable typing, no classes, hardly any of the familiar keywords public, interface, static, etc. To me it looked like a really loose, unstructured, messy language, and I missed my object-oriented ActionScript.

However, I have since learned that JavaScript is what you make it. Its flexibility is one of its strengths, and while sometimes I may still miss the keywords that were available in AS3, you can write JavaScript in an object-oriented way. You just need to make the effort. And study up on how to achieve this. This post will cover the basics of how to structure your JavaScript using OOP practices.

If the concept of object-oriented programming is new to you then I recommend you have a read up on what it is before going through this post. There is a lot of information on this on the internet, and many books you can buy on the subject, you’ll have no trouble finding info. I am assuming a basic knowledge of OOP, and that you, the reader, would like to know how to implement it into your JavaScript. I will try and follow up this post with some examples of using various design patterns in JavaScript, but for now let’s get started with the basics!


CLASSES

JavaScript does not have classes in the traditional sense, which can be confusing at first if, like me, you are coming from a classical programming language like AS3. In JavaScript we can create a class just by creating a function, and naming it with the class name (either by assigning it to a variable or just naming the function). And then into this function you can add variables and methods as properties of your class. Here is my class Dog:

var Dog = function()
{
  ......
};

Or:

function Dog()
{
  ......
}

It’s a matter of preference really. This is one of the quirks of JavaScript – there are often several ways of doing something, and you just need to pick which you prefer (and probably make an agreement with the other developers on your team). In this case, I like the first technique, so that is what I’ll be using throughout this post. I would recommend naming classes using an uppercase letter at the start – this just helps makes it clear that this is a class.


MODULES

You will probably have come across the term module before. Modules are a great way of containing JavaScript, keeping it inside the “black box”. They are also a guide to other developers about what you are intending to do. You create a module by making an anonymous self-executing function.

(function()
{
   ......
})();

The anonymous function is wrapped in brackets solely for a visual guide, they don’t have any functional goal. The () at the end calls the function you have just created.

When structuring my JavaScript, I will normally make one .js file per class, and put just this class into a module in that file. So let’s take our Dog and put it into a module:

Dog.js

(function()
{
  var Dog = function()
  {
    ...
  }; 
})();

And then I would assign my Dog to my application’s namespace so other classes have access to it. As with this current version of Dog.js there is no way of getting to the Dog after the anonymous function executes.

Dog.js


var MYAPP = MYAPP || {};

(function()
{
  var Dog = function()
  {
    ...
  }; 

  MYAPP.Dog = Dog;
})();


SCOPE

JavaScript differs from other languages in that you do not define the scope of a variable using keywords such as public or private. However, variable scope does exist in JavaScript and we can define private, privileged & public variables and functions. You will have been doing this already, maybe without realising. So let’s go over how to create each type.

Private

So, a private property is accessible only within that class. Let’s add a private attribute called breed and a private method called logBreed() (which references the private attribute) into our Dog class.

var Dog = function()
{
  // private variable
  var breed;

  // private function
  function logBreed()
  {
    console.log(breed);
  }
};

Easy! Neither of those properties can be accessed from outside of the Dog function, and so are private.

Public

Now, a public property is accessible from outside the class. You can do this in more than one way (surprise, surprise), and it is up to you to decide which you prefer or which is more fitting for a particular situation.

The first way we will look at is to use the this keyword and assign properties to it. In the following example this refers to the class Dog, and so when we assign properties to this we are adding them as properties of Dog.

var Dog = function(name)
{
  // private variable
  var breed;

  // private method
  function logBreed()
  {
    console.log(breed);
  }

  // public variable
  this.name = name;

  // public method
  this.microchip = function()
  {
    ......
  };
};

Another way to achieve this is by initially defining the public properties the same way as the private ones, but then returning an object from the constructor function which contains each property you want to be public.

var Dog = function(name)
{
  // private variable
  var breed;

  // private method
  function logBreed()
  {
    console.log(breed);
  }

  // define public variable
  var name = name;

  // define public method
  function microchip()
  {
    ......
  }

  // return public properties in object
  return {
    name: name,
    microchip: microchip
  };
};

And yet another way is to assign a function directly to the prototype object of the class. The prototype object can be a bit confusing to those new to JavaScript, but don’t worry, you don’t need to understand it perfectly to use this technique.

Using this technique, the public properties do not have access to any of the private ones, so it is not always feasible to use it. However, pulling code out of the constructor function is preferable wherever possible and practical, for performance’s sake. Each time a new instance of Dog is created, the code inside the constructor function will execute, and new instances of all the methods declared within the constructor will be created and stored in memory. By putting methods outside the constructor, only one instance of the method will be created and this one instance of the method will then be used for each instance of the class. This will save you memory if multiple instances of your class are instantiated.


// Dog constrcutor
var Dog = function()
{
  // private variable
  var breed;

  // private method
  function logBreed()
  {
    console.log(breed);
  }
};

// public variable
Dog.prototype.name = "Detective Woof";

// public method
Dog.prototype.microchip = function()
{
  ......
};

Privileged

A privileged method is one which is public but which accesses or alters private properties – a common example of this is a getter/setter method (also known as accessor/mutator).

var Dog = function(name)
{
  // private variable
  var name = name;

  // privileged methods access & update private variable name
  this.getName = function()
  {
    return name;
  };
  this.setName = function(value)
  {
    name = value;
  };
};


STATIC PROPERTIES

As I mentioned earlier, JavaScript does not have all the keywords for defining variables and methods that other programming languages do; and so you cannot simply define a variable as static by typing “static“. However, you can make it so a property acts as a static one, which is the important thing at the end of the day.

Private Static

Let’s start with private static properties. If you want to define these, then you are going to need to rework the constructor code of a class. Let’s return to our Dog, and add a private static variable called vet (as the vet for our dog instances is the same for all of them).

The first step is to make the Dog class a self-executing function.

var Dog = (function()
{
  .......
})();

Now we declare our private static properties within this self-executing function.

var Dog = (function()
{
  // private static variable
  var vet = "Happy Vet Clinic";
})();

And then we need to return the constructor as a function. The non-static private, public and privileged properties will be declared within this constructor function.

var Dog = (function()
{
  // private static variable
  var vet = "Happy Pet Clinic";

  // return the constructor function
  return function()
  {
    // private variable
    var name = name;

    // privileged methods access & update private variable 'name'
    this.getName = function()
    {
      return name;
    };
    this.setName = function(value)
    {
      name = value;
    };

    // access private static variable 'vet'
    this.getVet = function()
    {
      return vet;
    };
  };

})();

So what is happening here? Well, the first time this .js file is loaded and executed, the Dog class will execute, as it is now a self-executing function. This means that our vet variable is assigned as a property of Dog and the constructor function is returned as the value of Dog. So when an instance of Dog is created – new Dog(); – it already has the vet property and the function we returned within the self-executing function is run as the constructor.

Public Static

So what about public static? How do we do that? It’s a bit simpler (yay!) – we just assign a method or variable as the property of the class after we define the class. So it is put outside of the constructor, like when we added public methods to the prototype object. Just excluding the prototype keyword. This has the same limitation and performance boost that the prototype method has: you cannot access private properties, even private static ones, and you save on memory because only one instance of the function is ever created (rather than one per class instance).

var Dog = (function()
{
  // private static variable
  var vet = "Happy Pet Clinic";

  // return the constructor function
  return function()
  {
    // private variable
    var name = name;

    // privileged methods access & update private variable 'name'
    this.getName = function()
    {
      return name;
    };
    this.setName = function(value)
    {
      name = value;
    };

    // access private static variable 'vet'
    this.getVet = function()
    {
      return vet;
    };
  };

})();

// public static variable
Dog.numLegs = 4;

// public static method
Dog.bark = function()
{
  console.log("woof!");
};

CONSTANTS

A constant is a variable whose value is always constant ie. it is set once and never changes. You cannot define a constant using a particular keyword such as const in JavaScript. Rather, you just restrict the access so there is no option for the variable but for it to be treated as a const. There are several steps to this:

  • Create a private static variable (as covered in previous section)
  • Use uppercase characters in its name (as a signal to other developers that this is a constant)
  • Restrict access by only having a getter method, no setter

So for our Dog let’s add a constant that is an Array of all dog breeds.

var Dog = (function()
{
  // constant declared as private static variable
  var DOG_BREEDS = ["Golden Retriever", "Kelpie", "Westie"];
  
  // privileged static method for accessing const value
  this.getDOG_BREEDS = function()
  {
    return DOG_BREEDS;
  };

  // return the constructor function
  return function()
  {
    ......
  }
})();

And that’s it! Easy breezy.


INHERITANCE

In a more traditional classical language, inheritance is fairly straightforward in that when you define a class, you can also define another class for it to extend. In JavaScript we are missing this extend keyword, but inheritance is still possible by using the prototype object. There are 2 methods of inheritance that I will cover here, both use the prototype object, but in different ways.

Object Inheritance

So in this technique there are several steps to complete for you to get a class extending another. Within the constructor function of your subclass, you need to invoke the call() method of the superclass, passing in this as the scope. You set the prototype object of the subclass equal to the parent class, and then the prototype.constructor equal to the subclass. And then, tada! The subclass will have inherited all methods and variables of the superclass, and will be able to overwrite and customise them as necessary.

It sounds confusing to read it like that, so let’s see an example. Let’s create a subclass of our Dog class called Poodle:


// superclass Dog, taking parameter 'name' and assigning to 
// public property
var Dog = function(name)
{
  this.name = name;
};
Dog.prototype.getName = function()
{
  return this.name;
};

// subclass Poodle, taking parameter 'name' and new parameter 
// 'curliness'
var Poodle = function(name, curliness)
{
  // invoking call() method of superclass
  Dog.call(this, name);

  // new property unique to Poodle class
  this.curliness = curliness;
};

// set Poodle prototype object to superclass Dog - Poodle now 
// extends Dog
Poodle.prototype = new Dog();

// need to set constructor back to Poodle, as previous line 
// of code wiped out the constructor attribute
Poodle.prototype.constructor = Poodle;

// now we add unique functionality to Poodle prototype
Poodle.prototype.getCurliness = function()
{
  return this.curliness;
};

// and customise superclass' method
Poodle.prototype.getName = function()
{
  var name = Poodle.superclass.getName.call(this);
  return "Poodle " + name;
};

So the 3 steps for Object Inheritance are:

  • Invoke superclass.call() in subclass’ constructor
  • Assign new instance of superclass to prototype property of subclass
  • Set prototype.constructor property of subclass to subclass

Easy! (Sort of). But… It is still a lot of code to write each time you want to extend another class, which means more possibility of introducing bugs. To speed things up, and make them safer, let’s create an extend() method that you can reuse each time. So, let’s rewrite our Poodle using this technique.

// extend function to reuse each time
function extend(subclass, superclass)
{
  var F = function(){};
  F.prototype = superclass.prototype;
  subclass.prototype = new F();
  subclass.prototype.constructor = subclass;

  // assign superclass as a property to the subclass so we can 
  // access it
  subclass.superclass = superclass.prototype;
  if (superclass.prototype.constructor == Object.prototype.constructor)
    superclass.prototype.constructor = superclass;
}

// class Dog
var Dog = function(name)
{
  this.name = name;
};
Dog.prototype.getName = function()
{
  return this.name;
};

// class Poodle
var Poodle = function(name, curliness)
{
  // still need to invoke call() method here, but we reference 
  // property 'superclass.constructor' so we can keep flexibility
  Poodle.superclass.constructor.call(this, name);

  // new property unique to Poodle class
  this.curliness = curliness;
};

extend(Poodle, Dog);

// add new functionality to Poodle
Poodle.prototype.getCurliness = function()
{
  return this.curliness;
};

// and customise superclass' method
Poodle.prototype.getName = function()
{
  var name = Poodle.superclass.getName.call(this);
  return "Poodle " + name;
};

Prototypal Inheritance

This approach can look very unusual, but it works just as well. Both techniques work more or less the same, it is up to you to make your preferential choice. I’ll admit I find this too strange myself to use, but maybe this one makes more sense to you, or maybe you like that there are fewer lines to write… whatever, it’s your choice! So with this technique we first declare the superclass as a prototype object, and then use the clone() method to create instances of it. This sounds weird right? Let’s have a look.


// Dog prototype object
var Dog = {
  name: "default value",
  getName: function()
  {
    return this.name;
  }
};

// Dog instance
var fido = clone(Dog);
console.log(fido.getName()); // returns 'default name'
fido.name = "Fido";
console.log(fido.getName()); // now returns 'Fido'

// another Dog instance
var benny = clone(Dog);
benny.name = "Benny";

So that is how you create an instance, and set the properties. Now, how do we extend? First we assign the subclass to a variable that is calling clone() on the superclass. We then add the custom functionality for the subclass. And then we can create instances by cloning the subclass. So, let’s see our Poodle in this case:

// Dog prototype object
var Dog = {
  name: "default value",
  getName: function()
  {
    return this.name;
  }
};

// Poodle class
var Poodle = clone(Dog);
Poodle.curliness = "extremely"; // default value for all Poodles
Poodle.getCurliness = function()
{
  return this.curliness;
};

// Poodle instances
var puffy = clone(Poodle);
puffy.name = "Puffy";
puffy.curliness = "moderately";

var piffy = clone(Poodle);
piffy.name = "Piffy";

// outputs 'Puffy, moderately curly'
console.log(puffy.name + ", " + puffy.curliness + " curly");

// outputs 'Piffy, extremely curly'
console.log(piffy.name + ", " + piffy.curliness + " curly");

I have to admit I find this quite difficult to get my head around, but it is simpler than object inheritance, there is definitely less code. So it is entirely up to you and your team which approach you use. I would say though, that you should use the same approach throughout a project or things could get confusing.


INTERFACES

Interfaces are another feature of object-oriented programming languages, where you can use the keyword interface to define a signature that a class should conform to. Again, JavaScript does not offer this, but we can create an interface by being smart. When we say a class should implement an interface, we are saying it needs to contain those properties specified in the interface, or an error should be thrown. Now, how do we do this in JavaScript?

We start by creating a class that we can use to create an interface instance. What does an interface contain? It needs a name, and then a list of the methods a class that is implementing it should have.

var Interface = function(name, methods)
{
  this.name = name;

  this.methods = [];
  for (var i = 0, len = methods.length; i < len; i++)
  {
    if (typeof methods[i] !== "string")
      throw new Error("Interface needs method names passed in as strings");
    this.methods.push(methods[i]);
  }  
};

We can now instantiate new interfaces:

var IDog = new Interface("IDog", ["bark", "wagTail", "lickFace"]);
var ICat = new Interface("ICat", ["meow", "scratch", "hideInBox"]);

I used the old naming convention of putting an I at the start of the interface name, you don’t have to do this, but for me, old habits die hard. And I do think it is helpful to see straight up that something is intended to be an interface.

Now we need to be able to create a class and have it implement an interface. We do this by creating a method in the Interface class that ensures that a class is implementing the required methods. This method receives a class instance and one or more interfaces that it should implement as parameters. It then checks if each of the methods specified in the interfaces exist on the class instance as functions. If not, then an error is thrown. If all is well, then the code just continues to run. Here is the updated Interface class:

var Interface = function(name, methods)
{
  this.name = name;

  this.methods = [];
  for (var i = 0, len = methods.length; i < len; i++)
  {
    if (typeof methods[i] !== "string")
      throw new Error("Interface needs method names passed in as strings");
    this.methods.push(methods[i]);
  }  
};

// new method for checking if a class implements required methods
Interface.ensureImplements = function(object)
{
  if (arguments.length < 2) 
    throw new Error("Needs at least 2 parameters");

  for (var i = 1, len = arguments.length; i < len; i++)
  {
    var interface = arguments[i];

    if (interface.constructor !== Interface)
       throw new Error("Arguments 2+ need to be Interface instances");

    for (var j = 0, jlen = interface.methods.length; j < jlen; j++)
    {
      var method = interface.methods[j];

      // check method exists as a function in the class
      if (!object[method] || typeof object[method] !== "function")
        throw new Error("Interface " + interface.name + " not implemented; " + method + " not found");
    }
  }

  // if code execution reaches this point then interfaces are all 
  // implemented correctly, wahoo!

};

Then we can use this as so:

var IPet = new Interface("IPet", ["getName", "getAge"]);
var IDog = new Interface("IDog", ["bark", "wagTail", "lickFace"]);
var ICat = new Interface("ICat", ["meow", "scratch", "hideInBox"]);

// implements IAnimal, IDog
// it is also helpful to add a comment like this for other 
// developers where you say which interfaces a class should 
// implement, this just makes sure everyone knows what is 
// happening
var Poodle = function()
{
  ......
};

// create new instance of Poodle, and check it implements 
// interface - it may be more helpful to check it implements 
// the necessary methods before running some functionality that 
// actually requires these methods to exist, I'm just putting 
// it here as a quick example
var poodle = new Poodle();
Interface.ensureImplements(poodle, IAnimal, IDog);


WRAP UP

So that’s it! Those are the essentials for you to go and get started on structuring your JavaScript in a lovely object-oriented way. Hope this was helpful, and I will try and follow up this post with some examples of implementing particular design patterns in JavaScript.

I should say here, that a lot of this information I pulled from the amazing book Pro JavaScript Design Patterns by Dustin Diaz & Ross Harmes (link on Amazon here). If you are interested in more detailed information on this topic, or would like to have a selection of design patterns implemented in JS, I totally recommend buying this book. I have the kindle version and I love it.


Flash Performance

As I work in the online games industry, it is important that the games I make run smoothly in the players’ browsers. This means that we need to improve the performance wherever possible. After having focused on this for a while, I gathered together the different things I have learned. So here are some points to help improve the performance of Flash applications and help games to run smoothly and not overload your players’ machines.

Looping

For each loops can be up to 24 times more processor intensive than for loops, so if ever you can avoid using a for each loop, do.

for each (var item:MovieClip in myArray)
{
     trace (item.name);
}

for (var i:int = 0, len:uint = myArray.length; i < len; i++)
{
     trace (myArray[i].name);
}

Avoid recalculating data in each iteration of a loop, if you will need it inside the loop then store it in a local variable outside of the loop, or define it in the first step of the loop declaration. This is especially true of an Array’s length property.

var mathCalc:Number = 100 * 600;
for (var i:int = 0, len:uint = myArray.length; i < len; i++)
{
     // some code using mathCalc
}

// do
for (var i:int = 0, len:uint = myArray.length; i < len; i++)....

// rather than
for (var i:int = 0; i < myArray.length; i++)...

If you are going to use your iterator variable in any maths equation, cast it as an int first, as it will be treated as a Number otherwise and will take more processor power

for (var i:int = 0; i &lt; 10; i++)
{
     trace ("i * 5 = " + String( int(i) * 5 ));
}

It also helps to reduce the use of square brackets within a for loop if you are going to reference an item this way several times. It is more processor-friendly to just do it once and assign the value to a local variable.

for (var i:int = 0, len:uint = myArray.length; i < len; i++)
{
     var item:Object = myArray[i];
     trace ("name: " + item.name);
     trace ("x: " + item.x);
     trace ("y: " + item.y);
}

// rather than
for (var i:int = 0, len:uint = myArray.length; i < len; i++)
{
     trace ("name: " + myArray[i].name);
     trace ("x: " + myArray[i].x);
     trace ("y: " + myArray[i].y);
}

One of Flash’s odd quirks is that a while loop is faster when reversed:

var i:int = myArray.length; 
while (i-- >= 0) 
{
     ...
}

Graphics

Reusing instances rather than creating new ones can be a great way to improve performance, as whenever you use the “new” keyword Flash is doing a lot of work. You can destroy old instances, removing all event listeners, etc. and then store them in an Array until they are needed. For example, say you have a game which gives the player cards every turn, when the turn is over, destroy these cards and store them in an Array, and on the next turn pull these cards out of the Array and initialise them with their new values.

Here is a basic example:

private var _itemData:Array;
private var _oldItems:Array;

private function addItemsToDisplay():void
{
     if (_oldItems.length > 0) item = _oldItems.pop();
     else item = new Item();

     item.init(_itemData[i]);
     item.addEventListener(MouseEvent.CLICK, onItemClick, false, 0, true);
     addChild(item);
}

private function removeItemsFromDisplay():void
{
     while (numChildren > 0)
     {
          var item:Item = Item(removeChildAt(0));
          item.removeEventListener(MouseEvent.CLICK, onItemClick);
          item.destroy();
          _oldItems.push(item);
     }
}

Bitmap images are more processor friendly than vector graphics, as Flash is constantly redrawing the vector images whenever they are moved, scaled, etc. Bitmap images can increase the file size though, so you need to decide which is more important in your particular application. A good middle ground is to use a vector image, but set the cacheAsBitmap property to true. This property is on the DisplayObject class, and if set to true Flash will create a bitmap version of the image and not keep redrawing the vector graphic. However, if the image is rotated, scaled or has moving content such as animation then setting this property to true will actually have a negative effect on performance as Flash is not only redrawing the content every time it changes but it is then creating a bitmap version of this image and storing it in memory as well.

myDisplayObect.cacheAsBitmap = true

One way to check which areas of your application are being redrawn is to set Flash Player to show redraw regions. You can do this with the Ctrl+E shortcut on a PC, or use the menu View–>Show Redraw Regions. This will draw a red square around the areas when Flash redraws them. This can help you determine work Flash is doing needlessly by locating sections which don’t need to be redrawn.

Some other things to think about are using graphical filters like blurs and glows which can be very intensive on the CPU. Alphas can also be a lot of work for it too, and masks. Minimise these whenever possible, and especially avoid overlapping alphas.

One thing we do at my company is to completely take the animation work away from Flash by using FLVs instead of timeline animation. An FLV is a Flash video file that can be embedded in the timeline in Flash. This means we can have really great animation and effects without badly impacting the CPU, and has helped us to make some great looking games. However the trade off with this is the file size, so again you need to look at your particular application and work out what is best.

Miscellaneous

This is the optimum way to cast an instance as a Class:

//this is the optimum way
Class(instance).doSomething();

//rather than
(instance as Class).doSomething();

Another good thing to do is to use Vectors over Arrays whenever this is viable. Vectors are basically Arrays where you specify the class of the items that are held in it. This makes things easier for Flash and so looping and other methods are faster when using Vectors over Arrays and Vectors use less memory too. It is even better to set the fixed property and specify the length of the Vector during instantiation.

var myVector:Vector<MyClass> = new Vector<MyClass>(15, true);

// this Vector can only hold items which are MyClass
// this Vector as soon as it is instantiated has 15 items, which are null until set otherwise

myVector[0] = new MyClass();

Make sure to set mouseEnabled = false on all MovieClips and dynamic TextFields where you do not require any user interaction. The default for these is to have mouseEnabled = true and this means all these items have mouse listeners unnecessarily. It can be helpful to set mouseChildren = false on MovieClips which contain many child assets so you don’t have to individually set mouseEnabled = false on all of them.

If you are appending text to a TextField it is more performance friendly to use the myTextField.appendText() method rather than setting myTextField.text += “more text”

Calling functions means a lot of work for the processor. Obviously it is important to have object oriented code so don’t take this too far, but it is worth keeping in mind for those occasions where perhaps you could keep some functionality inline.

So these are some helpful points I have gathered for myself, hopefully they will be of some benefit to you too 🙂

Dragging – Detect when mouse leaves and is released outside SWF

The startDrag() and stopDrag() methods of the Sprite class are a great way to easily add dragging into your application. I came across a small issue when adding some dragging into some work of mine. If the user moves their mouse outside of the swf and releases it, when they return the item is still following their mouse even though it is no longer held down. There is a simple solution to this – you just need to listen for another event MouseEvent.MOUSE_LEAVE and store whether or not the user’s mouse is currently over your swf.

Code:

private var _mouseOverSwf:Boolean;
private var _dragCircle:Sprite;

public function Dragging()
{
	init();
}

private function init():void
{
	var circle:Sprite = new Sprite();
	circle.graphics.beginFill(0xFF0000);
	circle.graphics.drawCircle(250, 175, 50);
	circle.graphics.endFill();

	circle.addEventListener(MouseEvent.MOUSE_DOWN, onCircleMouseDown, false, 0, true);

	this.addChild(circle);
}

private function onCircleMouseDown(event:MouseEvent):void
{
	this._mouseOverSwf = true;

	var point:Point = new Point(this.mouseX, this.mouseY);

	this._dragCircle = new Sprite();
	_dragCircle.graphics.beginFill(0x00FF00);
	_dragCircle.graphics.drawCircle(point.x, point.y, 20);
	_dragCircle.graphics.endFill();

	this.addChild(_dragCircle);

	_dragCircle.startDrag();

	stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp, false, 0, true);
	stage.addEventListener(MouseEvent.ROLL_OVER, onStageRollOver, false, 0, true);
	stage.addEventListener(MouseEvent.ROLL_OUT, onStageRollOut, false, 0, true);
	stage.addEventListener(Event.MOUSE_LEAVE, onStageMouseLeave, false, 0, true);
}

private function onStageMouseUp(event:MouseEvent):void
{
	_dragCircle.stopDrag();
}

private function onStageRollOver(event:MouseEvent):void
{
	this._mouseOverSwf = true;
}

private function onStageRollOut(event:MouseEvent):void
{
	this._mouseOverSwf = false;
}

private function onStageMouseLeave(event:Event):void
{
	if (!this._mouseOverSwf)
		_dragCircle.stopDrag();
}