Wednesday, August 28, 2013

Pseudo-Random Number Generation (Seeded) in JavaScript

What, no seed on Math.random()? But I could've sworn...

I was faced with a situation where I wanted to produce random numbers from a seeded generator in JavaScript, and I noticed (strangely for the first time) that Math.random() is a random number generator, but not a pseudo-random number generator (PRNG). The problem I was trying to solve is that I wanted to create random numbers, but I wanted to be able to recreate the same series of random numbers.

The Mersenne Twister

So I hit the Googles, and immediately came across this post on StackOverflow that had a few solutions for PRNG. The post suggested that Mersenne Twister was one of the better algorithms for PRNG, but didn't really offer up code for that in JavaScript. So I Googled further and found that there was a JavaScript implemenation of Messente Twister, but I didn't like it, really. No offense meant to the original authors, but it seemed to be a port of a C or C++ implementation straight to JavaScript, and was a little bulky and not factored out enough for me.

TL;DR: I made an open source Mersenne Twister implementation in JavaScript

It's here on GitHub, hopefully someone else finds it useful. The goal was to keep it concise and compact.

What does it do? It produces evenly distributed random integers between 0 and 4,294,967,296 (aka 0x100000000) from a seeded generator.

BTW: If anyone is an expert in cryptography or mathematics please review my implementation.

Wednesday, August 14, 2013

Angular - $compile: How it works, How to use it.

What is a "View"?

A view is HTML, plain and simple. A view is a DOM element and it's children. Views will contain markup and directives in that markup.

What Views are "Compiled"? 

All views are compiled by Angular. This is done by code that lives in the $compile service area of Angular.

How does view compilation work?

View compilation in Angular is some of the most ingenious functional programming I've seen in JavaScript. It works (very, very roughly) like this:

  1. Step into a DOM node.
  2. Loop through registered directives to see if this node contains any.
  3. For each directive found:
    1. Determine if the current scope is to be used, or if a child or isolated scope needs to be created.
    2. Create a function that, when called, will execute the directive's linking function against the appropriate scope from step 3.1.
    3. Append that function to a list of functions to be executed later.
  4. Does the current DOM node have children?
    1. YES: Step into each one and go to step 1 above.
    2. NO: That's the end of this branch.
  5. Return a function that will execute all functions created in Step 3.2. This is your compiled view.

Binding a View to a Scope

This is done when the compiled view is called and a scope is passed to it.

When does this occur?

  • When you angular app is initially bootstrapped.
  • During the processing of some directives, such as ng-repeat, it will be called on a subsection of your views.
  • When ng-view is updated after a routing event it's called on the incoming view.
  • When ng-include changes, it's called on the incoming view.
  • I'm sure there are many more places I'm not thinking of, but those are the big ones I can think of that happen OOTB.

When should I use $compile?

Truthfully? Almost never. It's going to be pretty rare that you should have to compile some HTML and process it as a view. Generally, you can just use directives that already exist to do whatever it is you think you need to do with $compile. But I suppose there are some edge cases where you may want to use it. Such as creating a completely custom repeater or something like that.

If you do find yourself needing to use compile. It should almost always be in a directive. Think about it: $compile is creating a function to wire up directives to a scope... in essence setting up all interactions between your app and the DOM. When you see "DOM", it's a directive. Directives are where we should be manipulating the DOM and nowhere else.

An example of compiling a view manually

 * A weird directive that takes a space-seprated list of property names,
 * and prints them out as JSON.
app.directive('whatIsInThese', ['$compile', function($compile) {
    return function(scope, elem, attrs) {
        //getting a list of space-separated property names 
        //from the attribute.
        var these = attrs.whatIsInThese.split(' '),

        //start creating an html string for our "view".
            html = '';

        //append a bunch of bound values from the list.
        angular.forEach(these, function(item) {
            html += '{{' + item + '| json}}\n\n';

        //create an angular element. (this is still our "view")
        var el = angular.element(html),

        //compile the view into a function.
            compiled = $compile(el);

        //append our view to the element of the directive.

        //bind our view to the scope!
        //(try commenting out this line to see what happens!)

Here's a plunker showing the above directive at work. Play around with it if you like. It's a strange example, and the same thing could be done in better, more maintainable ways, for sure. But it gets the idea accross, I think.

TL;DR Version

View compilation in Angular basically traverses the entire DOM tree of whatever node you give it, creating a single function, that when called will execute every linking function from every directive it finds in that DOM tree, with the appropriate scope, element, attributes and (optionally) controllers.

Let's not forget those those linking functions are what are setting up your $watches and event bindings and all of your ties to the DOM.

And as always: READ THE SOURCE!

Remember, Angular is open source, if you want to know more about it, don't read my stupid blog, read the source!!! It can be found on GitHub.

Tuesday, August 6, 2013

AngularJS: $watch, $digest and $apply

While browsing reddit, I read an article I felt over-complicated an explanation of $watch, $digest and $apply, and perhaps gave people a little bit of the wrong idea about what it is.

What is a $watch? 

Let's talk about this first. $watch is arguably the most important internal feature of Angular. $watches can be used to watch any value, and trigger a function call when that value changes. A $watch can be set up from any $scope by calling $scope.$watch() as shown below.

Setting up a $watch

There are two ways to set up a watch, by expression, or by function. Technically, they both do the same thing. If you pass an expression (a string), it will be evaluated against $scope and converted to a function to be watched. If you pass a function, it just watches that function, with no conversion necessary.

By Expression

The following will watch 'foo'. Which is an expression evaluated against $scope.
//$scope.$watch(<function/expression>, <handler>);

$scope.$watch('foo', function(newVal, oldVal) {
    console.log(newVal, oldVal);

By Function

To set up a $watch by function, you can do the following, which is technically the same as what is shown above:
$scope.$watch(function() {
    return $;
}, function(newVal, oldVal) {
    console.log(newVal, oldVal);

Facts about $watch:

  • A watcher can evaluate any value.
  • A watcher's handler can execute anything when aforementioned value has changed.
  • All watchers are evaluated when $digest() is called.
  • If the first argument of a $watch is a string, it is $eval'ed into a function prior to registration. It's functionally equivalent to passing a function as the first argument, just with an extra step internally.

What is $digest?

At it's core, the important thing to know about $digest is that it loops through all watchers on the scope it was called on and it's child scopes. and evaluates them to see if they've changed, executing their handlers if they have. That's the important part you need to know.

How to call $digest:


What is $apply?

Simply put, it's a wrapper around $rootScope.$digest that evaluates any expression passed to it prior to calling $digest(). That's it.  So, if you're calling it by itself without passing an argument to it, you may as well just call $digest().

How to call $apply:

$scope.$apply('foo = "test"');
$scope.$apply(function(scope) { = 'test';
    $ = 'test';

So when does a $digest/$apply happen?

At key moments defined by the framework. The Angular framework has built in calls to $digest and $apply to it's services and directives as well as some internal calls. But basically it's like this, things like $timeout perform a setTimeout, then call $apply or $digest (it actual does a little more than that, but that's the basic idea). $http.get(), same deal, makes an AJAX call, returns it, then queues up a $digest.  Then there are directives, like inputs with ngModel for example. Updates to the input will also trigger a $digest. You get the idea.

How do $watch, $digest, and $apply relate to updating my view?

  • The directive registers a $watch that looks for a change in the model on the $scope. The handler will update the DOM element's value.
  • The directive registers an event handler of some sort in the DOM that will get a value from the DOM and apply it to the model in $scope. It will also call $apply or $digest.
  • When you update the model in the scope via some in-framework call... $http.get() for example, it kicks off a $digest after it completes.
  • The $digest checks the $watch the directive registered, sees the change and fires the handler associated to it, updating the DOM element.

Why does Angular work this way?

Since Angular wanted to use plain-old-JavaScript-objects (*POJSO© Ben Lesh 2013 all rights reserved!! Brought to you by Carl's Jr), a digest was the only real choice. Why? Well you can observe setter and getters on known properties real-time, but there's really no way to build an event into adding new values to or removing values from an object or array, particularly when it's done by an indexer, ala hash table or array index. So a digest becomes necessary. How do I know this? Because I tried to write my own framework and quickly found myself writing a half-assed version of Angular. The only other option that I know of would be to completely wrap the model observation up in a construct with set() and get() functions... think Knockout... which makes the JavaScript code uglier to deal with (IMO).

Some Guidelines For Use:

  • $watch
    • DO use $watch in directives to update the DOM when a $scope value changes.
    • DON'T use $watch in a controller. It's hard to test and completely unnecessary in almost every case. Use a method on the scope to update the value(s) the watch was changing instead.
  • $digest/$apply
    • DO use $digest/$apply in directives to let Angular know you've made changes after an asynchronous call, such as a DOM event.
    • DO use $digest/$apply in services to let Angular know some asynchronous operation has returned, such as a WebSocket update, or an event from a 3rd party library like Facebook API.
    • DON'T use $digest/$apply in a controller. This will make your code harder to test, and asynchronous operations outside of the Angular framework don't belong in your controllers. They belong in services and directives.
Remember these are guidelines, not hard, fast rules. More importantly, they're my guidelines, so take them with a grain of salt.

When to use $apply vs $digest?

[EDIT: for clarification on when these should be used] $scope.$digest should rarely be used outside of some very specific instances. Such as an isolated scope in a directive that might want to only update itself. Or, in an extreme edge case if a scope object has been created for some other isolated purpose. $scope.$apply or $rootScope.$digest should be favored most of the time, as the general desired effect is to update an entire view or model. 


I'm sure I butchered some part of the explanation above, but if you want to know more, get the information where I did... read the code!!!! You can get to all of this code right on Angular's repository on GitHub. It's extremely well commented, and extremely interesting code to look through.

EDIT: I'd like to thank Zeroto for his comment on reddit that pointed out a pretty serious omission on my part.