May 4, 2014

service in angularjs

AngularJs is different from other JavaScript client-side framework in that it use dependency injection to manage its components. Although dependency injection is not a new method, in fact it has been very successful for many years, it is a new approach in JavaScript client-side framework. So if you never use dependency injection in other language before, it is pretty confusing. The following is my notes on this topic.

There are basically two step to develop your angularjs application.

  1. package and register your components using module like the following.

    (function () {
      var module = angular.module("mymodule", ["ng"]);
      module.value("user", { firstName: "Johe", lastName: "Doe" };
      module.directive("userWidget",  function (user) {
          //user is injected here.
          return {};
      });
    })();
    
  2. Let angularjs run the show by using an injector inject the components you created.

    <body ng-app="mymodule">
      <user-widget></user-widget>
    </body>
    

In the first step, when the page is loaded, angualar bootstrap the application. In the process of bootstraping application, one important object called "injector" is created which is shared across the application. Normally your don't need to access the injector programatically, or manually create an injector by yourself, so you may have never heard about it, or you might think that module and injector are the same thing. But they are not. In fact, you can create multiple injectors, each of them use different modules. But in the following exercise, I will manually create one, because I want to know internals of module and injector.

For now, there are 5 kinds of components you write in angularjs, service, animation, filter, directive, controller. Anything which is not animation, filter, directive, or controller, is service. If the name service confuse you, you can call service as injectable. It can be anything like a string, a number, an object, a dom element or whatever. An "injectable" is not injected by module, but injected by a injector, which has information from modules. The following code create an injector.

var modules = ["ng"];
var injector = angular.injector(modules);

The services we created using module is not really service instance, but service provider. During the creation of injector, angularjs import the service provider we created. However the instance of service is not automatically created. In the following, I have modified angularjs's source code to expose the cached service providers in injector as injector._providerCache and expose the cached service instance as injector._instanceCache, in the following screen shot we can confirm this.

When the injector is asked for an component instance, the injector will firstly check whether the component instance is in cache, if it is true, then return it , if not, ask the corresponding component provider to create an instance, cache the instance, and return it like the following.

AngularJs allows your to create your service provider in several ways. module.provider() is the most flexible way among them. The provider passed into the method need be an object with "$get" method which return to the service.

module.provider()

var module = angular.module("module", []);
module.provider("greeter", function () {
  return {
    greeting: "hello",
    $get: function () {
      //here this refer to the service provider
      var greeting = this.greeting;
      return function (name) {
        console.log(greeting + "," + name);
      };
    }
  };
});
var injector = angular.injector(["module"]);
var greeter = injector.get("greeter");
greeter("Fred"); //output hello,Fred

The flexibility of module.provider() is that you customize customize it later. Let's say, the "greeter" provider is created by a third party company. And you want to customize it's behavior before it get injected. You can write the following code.

var mymodule = angular.module("mymodule", ["module"]);

mymodule.config(function (greeterProvider) {
  greeterProvider.greeting = "hi";
});

var injector = angular.injector(["mymodule"]);
var greeter = injector.get("greeter");
greeter("Fred"); //output hi,Fred

module.factory()

If you don't need such flexibility of service provider, you can use module.factory() method, which is a simplified version of module.provider() method.

var module = angular.module("module", []);
module.factory("greeter", function () {
  return function (name) {
    console.log("hello," + name);
  }
});

var injector = angular.injector(["module"]);
var greeter = injector.get("greeter");
greeter("Fred");

Behind the scene, the module.factory() still create service provider internally exactly like created by the module.provider(), the result of the following is identical to the result of above code.

module.provider("greeter", function () {
  return {
    $get: function () {
      return function (name) {
        console.log("hello," + name);
      };
    }
  };
});

module.service() -- don't use

AngularJs also has a module.service() method which is very similar to module.factory(). In fact, in the above example, you can replace the module.factory() method with module.service(), the final result is the same (but the calling method is different), like the following.

module.service("greeter", function () {
  return function (name) {
    console.log("hello," + name);
  }
});

So why do we need a service method? How is the difference between this two. The source code angularjs show that the service method internally call factory method like the following.

function service(name, constructor) {
  return factory(name, ['$injector', function ($injector) {
    return $injector.instantiate(constructor);
  }]);
} 

This means that the factory method can do all the thing that that service method can do. The difference is that provider function is treated as constructor, it is called like "new constructor()". The following shows the difference

module.service("user", function () {
  this.firstName = "John";
  this.lastName = "Doe";
});

module.factory("user", function () {
  return {
     firstName: "John",
     lastName: "Doe"
  };
});

So when should we use service method, when should we use factory method. So far I never encounter a case when I have to use service method, and factory method is not able to do so. So my opinion is that, never use "service" method, always use "factory" method, because "factory" method simpler and more capable.

module.value()

If you look at the factory method, the "$get" member of real provider is a function which return a instance of the provider. Why can't the "$get" member be just the instance itself? Ok, angulajs has another method "module.value()" which try to meed this need. The value method simply return the instance like the following.

module.value("greeter", funnction (name) {
  console.log("hello," + name);
});

module.value("user", {
 firstName: "John",
 lastName: "Doe"
});

However, internally, the value method is like the following

function value( name, val ) {
 return factory( name, function() {
   return val;
 });
}

So the value method still convert the value into a provider which provide the value internally. But the question, "Why can't the "$get" member be just the instance itself instead of a function which provide the value?" is still not answered. What is the benefit of doing that. Let's look at the following code.

module.value("user", {
 firstName: "John",
 lastName: "Doe"
});

module.factory("greeter", function (user) {
  return function () {
   console.log("hello," + user.firstName + "," + user.lastName;
  };
});

In the above code, the greeter depends on user, the user is passed in the factory method by the injector. If the "$get" is the instance, but not a function, the "user" dependency will not be able to injected. However, if your instance does not have external dependencies which need to be injected by injector, you should use "value" method, which is more expressive, otherwise use "factory" method instead.

module.constant()

All the method above create service provider, which can return a service instance. module.constant() is different in that it does not create service provider, but it create the service instance directly. What this means is that it cannot be configurable using module.config(fn). Before you use injector.get(constantKey) to get the instance, it is already created and cached, like the following.

module.config(fn)

AngularJs has one more method module.config(fn) allow you config imported service provider. When an injector is being created, all the service providers created by the module.provider(), module.factory(), module.service(), module.value() is imported first using $provide. Then the config functions will run. The $provide dependencies can also be injected into the functions, the service providers created can also be injected into the functions. For example, if you create a service call "greeter", the "greeterProvider" can be injected into the config functions, but not the "greeter", because at this stage you are about to customize "greeterProvider" to create "greeter", that is why "greeter" can not be injected. This has been shown in previous demo

Also module.config allow you to create service provider using $provide object. The $provide object has the following method

$provide.provider(key, value); 
$provide.factory(key, value);
$provide.service(key, value);
$provide.value(key, value);
$provide.constant(key, value);

$provide.decorator(key, value);

AngularJs use the first 5 methods to import the service provider created using module method. For example, $provide.provider(key, value) is used to import the provider created by module.provider(key, value), so far and so on. But the question is why we want to use $provide in config function to create service provider directly instead of using the method of module, as they looks like do the same thing? In fact, in AngularJs use the config method the directly create service provider, like the following, but not using module methods.

var ng = angular.module("ng", []);
ng.config(function ($provide) {
$provide.provider({                              
    $anchorScroll: $AnchorScrollProvider,        
    $animate: $AnimateProvider,                  
    $browser: $BrowserProvider,                  
    $cacheFactory: $CacheFactoryProvider,        
    $controller: $ControllerProvider,            
    //..and more 
});                            
});                  

Honestly, I don't have an definite answer. But I think it is different way to organize your code, maybe AngularJs team think that is better for code minification or file organization. But the module method is good enough to organize application level development (vs framework development).

The $provide.decorator() is most interesting method of $provide object. You can use it to extend existing service provider. The following is an example

var module1 = angular.module("module1", []);
module1.value("name", "John");


var module2 = angular.module("module2", ["module1"]);
module2.config(function ($provide) {
  $provide.decorator("name", ["$delegate", function (oldInstance) {
    return oldInstance + "," + "Doe";
  }]);
});


var injector = angular.injector(["module2"]);
injector.get("name"); //name is John,Doe

If you have question about service dependency injection in angular, please leave me a note below.

Apr 3, 2014

Aliasing angular key concepts

AngularJS is a single page application framework. Although, it never markets itself as a "MVC" framework, it uses lots concept of MVC, like model, view, controller. Once you start using it, you will find the concepts it use does not map 100% to your concepts. So I feel that I need to alias these key concepts to align to my understanding. If you don't understand these concept correctly, you can use them in a wrong way very easily, because AngualrJS allow you to do so. In the following, I try to explain them by giving each of them an alias. Although an alias is not trendy, but at lease it helps me to understand. Hopefully, it helps you too.

service : injectable singleton

The term "Service" is a used every where, it means different things to different people in different context. AngularJs uses dependency injection to create almost all the reusable objects. Angularjs call this kind of object service. So the name service is probably not your concept of service, technically service is injectable singleton. It can be a piece of data, a method, or anything. A injectable object has lots of benefit, such as it is easy to test, customize, extend. In a word, angularjs recommend you to create all your reusable of "things" as service. The following artifacts such directive, scope, controller everything is kind of "service" internally in angularjs.

directive : behavior builder

AngularJS turns a static html document into an application. The application is still composed by DOM elements, but these elements has behavior. When the page loaded, AngularJS parsed the html document recursively for some special tag, attribute, or class name which map to something called "directive", which attach behavior to the DOM elements. The behavior can be reflected as the following.

  • Handle data event of scope, and change DOM
  • Handle DOM event, and change the data of scope
  • Handle change event of scope, and change other data of scope. This is not good practice, you can do it by other means
  • Handle DOM event, and change DOM. This is necessary sometimes, but it is not a good practice in general.

scope : model context

On the view site, there is DOM, which is a tree of html elements and attributes. On the model side, there is scope which is organized as tree. Angularjs attach each DOM element with a scope, so scope is like a context to describe model. When you stand on a DOM node, and talk about a model concept such as "customer", the concept "customer" is within a context (scope). When you stand on another node, the same concept of "customer" may or may not be the same thing depending on the whether two node sharing the same context (scope)

  • The most important functionality of model context is change detection. When data change, implement behavior in directive.
  • Expose read/write access to data to view.
  • Generate custom data event which can be passed up to ascendant model contexts
  • Generate custom data event which can be passed down to descendant model contexts

controller : scope builder

A DOM element is associated with one and only one scope. This scope can be inherited from the scope of parent DOM element, or it can be explicitly created by directive ng-controller or other directive. Directive ng-controller is implemented by module.controller() method. Other directive which create a new scope is implemented by module.directive

Apr 16, 2013

angularjs-sugar

The normal way to to creating anguarjs component is like the following.

var sugar = angular.module('sugar', []);
sugar.controller('controller1', function($scope) {
  $scope.m1 = m1;
  $scope.m2 = m2;
});
sugar.config(configFn);
sugar.constant("constant1", object);
sugar.directive("directive1", directiveFactory);
sugar.factory("factory1", providerFunction);

sugar.filter("filter1", filterFactory);
sugar.service("service1", constructor);
sugar.value("value1", object);
//....

I have created a script to simplify the process, so that you can write code like the following.

//angular.m("sugar", [dep1, dep2], definition);
angular.m("sugar", {
  controller: {
    test: function ($scope) {
      $scope.$extend({
        m1: m1,
        m2: m2
        };
      });
    }   
  },
  constant: {
    constant1: object
  },
  directive: {
       directive1: directiveFactory
   },
  factory: {
     factory1: providerFunction
   }
   //....
});

//you can split the definition in to multiple piece
angular.m("sugar", definition1)
angular.m("sugar", definition2);

The good things about it are:

  1. It is not easy to create global variable
  2. The code is more readable
  3. You can create all module components in a single call, this is useful for simple application.

You can get the code at https://github.com/fredyang/angularjs-sugar. And there is an example at Plunker.

Feb 9, 2013

Harmony.js

I haven't updated the blog for some time. Because I am working on an interesting JavaScript UI Library, Harmony. Like other JavaScript library such backbone.js, knockout.js, it tries to build HTML application in a structured way. What is unique is that it does not a have controller or binder. The models and views are pretty much on their own. They all take care about themselves by subscriptions. Are we going back to the age that we have tons of event handlers like spaghetti? Far from it. There are really lots of subscriptions and their handlers, but they are structured in a way that feels like object-oriented. The subscriptions and handlers are part of the objects (views and models). The views and models are treated like Human being in Harmony, they make decisions on their own, they respect each others, they are not manipulating or commanding each others.

It does not feel like programming. I agree. I have written an introduction and some documentations. I also wrote a evaluation app, todos, I am satisfied in that the views and models are shorter and more semantics than other implementations in todomvc.com. But it is just my personal feelings, let me know what you feel about it.

Apr 24, 2012

"use strict" and "this" in ES5

"this" is a special variable in JavaScript. If a Constructor function is called without "new", the "this" variable inside the constructor will reference the Global object. We can use "use strict" in ES5 to prevent this happening.

(function () {
  "use strict";
  console.log(this === window); //false
 })();

You can also use the "use strict" in global, but this will affect all module

 "use strict";
 console.log(this === window); //true
 (function () {
  console.log(this === window); //false
 })();

Dec 23, 2011

Why dynamic resource loading is so important for web application?

When I finished matrix.js 0.1, I asked for feedback from my friends. But the general response seems that I am trying to solve a problem which does not exist, so the library is useless. But I am not disappointed. I make it not because we have a pain point in my current projects, but because I see it is the way that we need to build future web application. It is better to explain what the problem is as I see, before I propose on a solution. I believe that, as we are developing web application, dynamic resource loading will be a essential function. The current way to import resource using <link> <script> tag statically and tools like combres will not be able to meet the needs of building web application.

The future web application? Isn't that we are a building web application. Yes, in a way we all building web application. There are two extreme of web application. On one extreme, web application completely depends of the <form> tags, all interaction depends on form postback, and page get re-rendered, one example are government web sites. On other extreme, web application does not have <form> tag, all interaction depends on ajax call, all UI is generated by JavaScript, template and the application stay in the same url until it is closed by user. This kind of application is fast and fluid, is as responsive as native desktop application. Gmail is an example close to this extreme. We are normally building web applications somewhere in between these two extreme.

To increase the loading speed of website, Minimize HTTP Requests is one of the rules listed in "Best Practise for Speeding Up Your Web Site". In .net, to minimize http requests, a popular approach is use tools like combres to combine, minified, gzip a set of resource, configure response header for client side caching. So that one big JavaScript file and one css file are generated and cached at client side. When we are building our current applications, the resource like JavaScript, css can be known more or less in advance. Because all pages in the website pretty much share some library like jQuery, a couple of widget plugin, like calendar, accordion, auto complete and so on. We can hand pick a set of resources required in specific page, or for the whole website. If we have a page require very different set of resources, we may need to pick another set of resources targeted for that page. So far so good.

As we are moving to an other extreme, building web application like Gmail, or even more complex, the architecture of our application changes. In this extreme, the application is responsive as desktop. The application compose and aggregate lots UI modules, or views, each views has their unique resource, and in a lot of case, we cannot anticipate which views will be used by user. All the views are built on demand of user. We need to load lots of client side template, view specific JavaScript, and unload them when view is not used, because the application is open for 8 hours a day continuously, memory management is critical for good client side performance. These requirements can not be solved by combres or statically resource loading. Combres can shorten the time to transfer resource from the server to browser. But it can not solve our architecture requirement like client side memory management, reusable, modular component design, dependencies tracking among resources. This resource is like Dynamic-link library, but it just happens at browser. Browser is our VM, not CLR not JVM. In .net, CLR is the run time. Assembly(DLL or EXE) is reusable unit. The loading of assembly is highly sophisticated. Here are some features.

  • Assembly Manifest contains of dependencies of dll/exe
  • Appdomain
  • Security check
  • Late binding
  • Dynamic loading

matrix.js is my starting point of building a true web application. I try to address similar issues we have like in assembly loading in .net, but I just do it for the browser vm not for CLR or JVM. Unlike CLR, browser vm has some advantage CLR does not have. In CLR, you can release your DLL, until you kill your AppDomain, in browser, you can unload everything dyanamically. You can remove DOM elements, you can unload a library , like jQuery by calling "delete window.jQuery", you can unload css by remove the link tag.

As we move to web application extreme more and more, preload two resource files (one js, one css) is like we load one gigantic EXE for a win32 application. Not only it is bad from the aspect of memory managemeent, it is even worse from the aspect of software engineering. It become monolithic artifact, while we want to have modular, reusable component.As HTML5 is ready, we will be building more and more application like Gmail and more complex, I believe dynamic resource loading is essential but not a fancy feature. Maybe you don't see the need to build a true web application right now, if you have, you can check out matrix.js