WinJS.Promises – lessons learned

WinJS.Promises – lessons learned

Goal of the promise is to bring the asynchronous programming into JS. It’s not new thing. You can find many information on wikipedia.

WinJS comes with built-in support of Promises. You can find more info on MSDN here.

Usage scenarios

  1. You call a native API which can take a long time. The call is started on UI thread. If it would take longer than 50ms and execute completely on UI thread, the user experience would be bad. The solution is to switch the execution to the background thread and later continue the work back on UI thread. In other words, API returns a promise object promising us that it will completed sometime later.
    var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
    openPicker
        .pickSingleFileAsync()
        .then(function (file) {
            // do something with file
        });
    
  2. Splitting the work which runs on UI thread into several small chunks so the UI thread is not blocked. The result is that the whole execution time is longer but the application is more fluid, the UI thread is not blocked. It’s implemented via a call to setImmediate. This is very much used inside WinJS
  3. You build a library with a flexible API accepting an input which is not in your control. To make the API more robust, be prepared for longer data loading. In that case it’s recommended to use Promise and the consumer of that API can provide synchronous (fast case, 50ms) promise.

WinJS team did a great work and implemented built-in support of Promises for us.

In this article I’d like to summarize my personal experience with Promises, after using them for more than 1 year.

They have a state

They are built on the state machine. This means the promise has its internal state (i.e. created, working, completed, canceled ,error) and the methods which moves the state machine from state A to B. It’s good to keep it in mind, especially when you combine promises, i.e. chaining, joining promises, waiting for any promise.

Creating a promise

There are several ways how to do it:

  1. WinJS.Promise.wrap(value): it creates a completed promise with the result: value.
  2. WinJS.Promise.as(value): it checks if the value is promise and then returns it. Otherwise it’s same as WinJS.Promise.wrap(value). I use mainly this option.
  3. Calling new WinJS.Promise(completed, error, progress). The parameters are functions and none of them is required. If the promise is created, WinJS tries to complete it directly. If the promise is added to the chain (so other promises are in the chain before the created one) then the functions completed/error are called based on the previous promise result. Huh, starting to be complex, right? Yeap, but quite powerful.
    var promise = new WinJS.Promise(function(complete, error, progress) {
        setTimeout(function() {
            // do some work
            complete(sum);
        }, 1000);
    });
    

Chaining the promises

It’s possible to chain the promises:

var promise = WinJS.Promise.timeout(1000)
    .then(function() {
        //do some work
    })
    .then(function() {
        //do some work
    })
    .then(null, function(error) {
        //error handler
    });

This means that when the first promise finishes, the next promise in the chain is executed.

Returning a value from promises

Any value returned from the promise is translated back into the completed promise with the return value.

var promise = WinJS.Promise.timeout(1000)
    .then(function() {
        return 1 + 1;
    })
    .then(function(sum) {
        console.log(sum); // prints 2
    })
    .then(null, function(error) {
        //error handler
    });

Postponing the work, timeout-ing

Javascript developers are very used to use two ways how to postpone the work:

  1. msSetImmediate(function)
  2. setTimeout(function, milliseconds)

WinJS.Promises has the equivalent via calling one method: WinJS.Promises.timeout(milliseconds). If milliseconds are omitted or equal to 0, then msSetImmediate is used, otherwise setTimeout.

This is very useful technique when it’s necessary to execute CPU sensitive task while keeping UI responsive. It’s necessary to split the long CPU sensitive tasks into chunks and chain them with several timeouts (WinJS.Promise.timeout())

WinJS.Promise.as()
.then(function () {
    // do some work (part #1)
    return WinJS.Promises.timeout();
})
.then(function () {
    // do some work (part #2)
    return WinJS.Promises.timeout();
})
.then(function () {
    // do some work (part #X)
})
.done();

When timeout() is called, UI thread is able to process other tasks waiting in UI thread queue (i.e. user’s clicks, etc) and it keeps UI responsive.

Cancelling the promise

var p = WinJS.Promise.timeout(1000)
    .then(function () {
        return 1 + 1;
    })
    .then(function (sum) {
        console.log("Sum is " + sum);
    })
    .then(null, function (error) {
        //error handler
    });

console.log("Cancelling the promise");
p.cancel(); 

After call to cancel the promise, the promise finishes the current execution but stops the further promises in the chain execution. In the above example, “sum is 2” is not printed.

Failing the promise

There are several possible ways how to fail the promise:

  1. Returning the wrapped error promise
    var p = new WinJS.Promise.wrap(10)
        .then(function () {
            return WinJS.Promise.wrapError("error promise");
        }).then(null, function (error) {
            console.log("Promise error " + error + " occured but was handled");
        });
    
  2. Throwing the exception
    var p = new WinJS.Promise.wrap(10)
        .then(function () {
            throw "custom exception";
        }).then(null, function (error) {
            console.log("Promise error " + error + " occured but was handled");
        });
    
  3. Calling error callback
    var promise = new WinJS.Promise(function (complete, error, progress) {
        if (shouldComplete) {
            complete();
        } else {
            error("failing it");
        }
    });
    

Failing the promise has the following consequences:

  • when it’s the first level promise (it’s not nested promise done via join/any call), then failing the promise raises WinJS.Application.error event which by default terminates the application.
  • the failed promise is in the error state, its returned value is null
  • can be used to manage the execution flow in aggregating the promises via join/any (see bellow)

Aggregating the promises

It’s possible to create an aggregated promise which will continue when all promises (in case of join) or at least one of the promises (in case of any) are completed.

WinJS.Promise.join

There are two possible ways of passing the promises:

  1. Join the promises defined as object fields.
    var promises = {
        p1: new WinJS.Promise.wrap(1),
        p2: new WinJS.Promise.wrap(2),
        p3: new WinJS.Promise.wrap(3),
    };
    
    WinJS.Promise.join(promises).then(function (args) {
        console.log("p1: " + args.p1); // writes 1
        console.log("p2: " + args.p2); // writes 2
        console.log("p3: " + args.p3); // writes 3
    });
    
  2. Join the promises defined as an array of the promises
    var promises = [new WinJS.Promise.wrap(1), new WinJS.Promise.wrap(2), new WinJS.Promise.wrap(3)];
    
    WinJS.Promise.join(promises).then(function (args) {
        console.log("0. promise: " + args[0]); // writes 1
        console.log("1. promise: " + args[1]); // writes 2
        console.log("2. promise: " + args[2]); // writes 3
    });
    

As you can see above, the completed result of the joining promise is the input object/array with completed promises.

WinJS.Promise.any

There is also a second type of aggregated promise called “any” promise and it continues the execution when any of the input promises (object properties or array) are completed.

Managing the execution flow, passing the values

It’s possible to pass values using closure or using WinJS.Promise.join and passing the object with properties which contains promises or values. Let’s see it in action.

Example #1

Let’s say we are copying files (imagine promises p1, p2) and after all files were copied we want to check what was copied successfully. In the next sample p1 simulates first file failed, but we handled it. P1 result will be null, promise will be completed.

var p1 = new WinJS.Promise.as()
    .then(function () {
        console.log("Copying file P1");
        throw "custom exception #1";
    }).then(function (value) {
        console.log("P1 done");
        return value;
    }, function () {
        //log error, cleanup if required
    });
var p2 = new WinJS.Promise.as()
    .then(function () {
        // copy file 
        console.log("Copying file P2");
        return {}; // simulating a handle object
    }).then(function (value) {
        console.log("P2 done");
        return value;
    }, function () {
        //log error, cleanup if required
    });

WinJS.Promise.join({ 
     p1: p1, 
     p2: p2, 
     m3: 3})
.then(function (args) {
    //args.p1 = null
    //args.p2 = promise with handle to file
    //args.m3 = 3
    console.log("Joined promise completed");
}, function (error) {
    console.log("Joined promise error '" + error + "' occured but was handled");
}).done();

//output:
Copying file P1
Copying file P2
P2 done
Joined promise completed

Example #2

Let’s say we are copying files (imagine promises p1, p2) and after that we want to continue if ALL of the files are copied completely. In the next sample p1 simulates that copying first file failed so the whole promise failed. This means also joining failed.

var p1 = new WinJS.Promise.as()
    .then(function () {
        console.log("Copying file P1");
        throw "custom exception #1";
    }).then(function (value) {
        console.log("P1 done");
        return value;
    });
var p2 = new WinJS.Promise.as()
    .then(function () {
        // copy file 
        console.log("Copying file P2");
        return {}; // simulating a handle object
    }).then(function (value) {
        console.log("P2 done");
        return value;
    });

WinJS.Promise.join({ 
     p1: p1, 
     p2: p2, 
     m3: 3})
.then(function (args) {
    //args.p1 = null
    //args.p2 = promise with handle to file
    //args.m3 = 3
    console.log("Joined promise completed");
}, function (error) {
    console.log("Joined promise error '" + error.p1 + "' occured but was handled");
}).done();

//output:
Copying file P1
Copying file P2
P2 done
Joined promise error 'custom exception #1' occured but was handled

Notes:

  • inner promises (p1, p2) are left to fail
  • error object contains failed promises with error description

Logging the failed promises

It’s possible to get notified when any promise failed via attaching the listener to “error” event exposed on WinJS.Promise class.


function handlePromiseError(error) {
    console.log("PROMISE ERROR OCCURED " + (error.detail.exception ? error.detail.exception : ""));
};

WinJS.Promise.addEventListener("error", handlePromiseError);

Finishing the promises UPDATE!

Promise chain can end with .then() or .done() call. But there is a difference. Based on the official documentation http://msdn.microsoft.com/en-us/library/windows/apps/hh700337.aspx the difference is that when the promise failed finishes with

  • .then() – then the error is raised on WinJS.Promise.error and that’s all. The error is silently captured
  • .done() – then the error is raised on WinJS.Promise.error and then there is a code
                    setImmediate(function () {
                        throw value;
                    });
    

    which raises general application exception raised via WinJS.Application.error.

That’s clear. But the default promise usage/error handling within WinJS application is little bit different. When the application is started, call to WinJS.Application.start(), there is a default promise error handler attached to WinJS.Promise.error. This handler raises WinJS.Application.error when the failed promise doesn’t have parent promise.

There is also a default error handler attached to WinJS.Application.error which when called terminates the application by default.

Result of .done()/.then()

When you create WinJS application project and copy the samples from above MSDN link to your project, you find out, that the samples don’t work as described. The failed promises (both ending with then or done) terminates the application.

Reason: failed promise raises WinJS.Promise.error event which is by default handled and in case the failed promise doesn’t have any parent, WinJS.Application.error event is raised. Its event handler terminates the application.

Anyway, lessons learned: In general the best practice both for behavior and code readability is to use .done wherever you can and use .then wherever you have to.

Writing the promise to be readable

Chaining the promises can become very unreadable. My lessons learned are:

  1. You are chaining the promises and you want to return value. Don’t wrap value into the promise, return just the value. It gets automaticaly wrapped into the promise
  2. Don’t create inner chain the promises when not required and just chain them on the upper level

Bad style

	
p.then(function () {
    return asyncWork().then(function (result) {
        return moreWork().then(function (anotherResult) {
            return finishWork();
        });
    });
});

Good style

var p = WinJS.Promise.as();
p.then(function () {
    return asyncWork();
}).then(function (result) {
    return moreWork();
}).done(function (anotherResult) {
    return finishWork();
});

Chatching errors

Errors raised from the asynchronous code written using promises are hard to catch because the callstack doesn’t reflect where the error occurred but where how it was propagated in WinJS.Promise state machine. The recommended approach it turning on immediate catching JavaScript Runtime Exception in Visual Studio->Tools->Exception settings.

WinJS.Promise.as()
.then(function () {
    throw "custom exception";
}).done();

Callstack:
>	terminateAppHandler [base.js] Line 6928	Script
 	Application_errorHandler [base.js] Line 7097	Script
 	dispatchOne [base.js] Line 6998	Script
 	dispatchEvent [base.js] Line 6998	Script
 	drainQueue [base.js] Line 7038	Script
 	queueEvent [base.js] Line 7057	Script
 	Anonymous function [base.js] Line 7190	Script
 	Anonymous function [base.js] Line 7189	Script

Please note, there is no info where the exception actually occurred.

WinJS.UI.ListView and its LayoutNotInitialized exception

While using WinJS.UI.ListView control and hiding/showing it together with binding/setting its datasource, it’s very possible to get the annoying exception “Layout is not initialized“.

Sample application

I developed a sampe app (after downloading just remove docx extension) where it’s possible to see when the exception is thrown.

The issue occurs in 2 cases:

  1. Given the ListView is hidden (display:none) and it is connected (via binding or JS) to empty list.
    When a new item is inserted into the datasource
    Then the ListView would like to render it but it’s necessary to measure the item size. Because of seeting “display:none” it is not possible, so mesureing fails and the exception is thrown
    Steps: check display none, click regenerate empty list, click add tile
  2. Given the ListView is hidden (display:none) and it is connected (via binding or JS) to non-empty list.
    When the items datasource is reset (via binding or JS) to some other non-empty datasource
    Then the ListView would like to render it but it’s necessary to measure the item size. Because of seeting “display:none” it is not possible, so mesureing fails and the exception is thrown
    Steps: check display none, click regenerate non-empty list

Solution

  1. using groupInfo property of layout which tells ListView: don’t measure on your own, here is the size
  2. when showing/hiding the listview we could enable/disable binding/setting the datasource

It’s possible to see both solution in the action in the downloaded application.

Summary

Solution a) is quite easy to do but it is not as performant as solution b.
Solution b) is better from the performance point of the view because when the listview is hidden and unbound, then it doesn’t receive and process any updates from datasource.

DataTemplate: solution to performance problems with WinJS Templates and binding

Problem: peformance issues with WinJS Templates and binding

WinJS Templates and Binding belongs to core parts of WinJS. Especially they fit very well into MVVM model, declarative binding, separation of concerns (UI logic contains really only UI logic)

Template rendering has the following high-level steps:

  1. optionaly create new container element which will contain a final rendered HTML – this step is optional because a result container can be passed as argument to the method)
  2. clone the template and append it into the container
  3. call WinJS.UI.processAll function on the root
  4. call WinJS.Binding.processAll function on the root and passed binding context objects (aka datacontext object)
  5. return the result

In addition, the whole process is wrapped into promises.

This process works quite well and you can achieve nice results with it. The problem starts when you try to finetune the performance. This is the slowest way of rendering item. There are several other ways which you can find in any WinJS docs/books.

WinJS Template and declarative binding is the slowest approach but the most flexible and I’d like to use it as often as possible but the performance has to be improved.

Let’s measure it!

Download MeasuringTemplatePerformance.zip and run the sample! (after downloading the file, remove extension docx, then unzip it) The sample I attached to this blog post is used to generate the color palette with the divs, using CSS3 grid layout. It does it in different ways and it measure the time spent.

Let’s review each solution.

Manual render

This is the fastest way and we will use it as our unit of measure. It’s the quickest way (at least for me) how to solve our problem. The only issue is that all UI logic (creating DOM elements, setting properties, etc) are done in codebehind, so there is NO separation of concerns.

Cloning render

It differs from manual process in the way how DOM elements are created – they are cloned form a template (do not mix it with WinJS template). In this case, the template is DOM element (acts as prototype) and we create cloned DOM element from the prototype and again, manualy set properties.
This is cca 3x slower than manual and still we violate separation of concerns.

Template, manual binding, manual placing in DOM

This approach uses WinJS template and its render method but it manually sets the properties (it doesnt use binding mechanism at all).
This is cca 7x slower than manual approach and again we violate separation of concerns.

Template, manual binding, auto placing in DOM

Similar approach as the previous case with just one difference: the result is directly added into DOM.
This is cca 11x slower then manual approach and again we violate separation of concerns.

Template, declarative binding, auto placing in DOM

This approach uses fully standard WinJS way of rendering, binding and adding the result to the DOM.
This is cca 30x slower than manual rendering but with full separation of concerns.

How to make the situation better?

The only solution is to reduce JS code to be executed. The source of the issue are two:

  1. calling WinJS.UI.processAll inside WinJS.Binding.Template.render – it could be totaly skipped as we don’t need to process any inner win controls.
  2. calling WinJS.Binding.processAll inside WinJS.Binding.Template.render – It could be rapidly enhanced. It’s overlook very often that WinJS.Binding.processAll has an optional argument called “bindingCache”. It is an object with specific interface and several usages:
    1. store all binding created during the binding process,
    2. cache parse all bindings found in the template
    3. stores all elements IDs with the bindings

Passing “bindingCache” can be reused for future binding process and it will speed up the binding process very much. Let’s see it in the action.

Template, cloning, declarative binding with binding cache, manual placing in DOM

This approach runs the binding process over the template element just to build the binding cache. Then for each data the template element is cloned and bound with support of binding cache. The difference is huge, IMHO.
This approach is slower only cca 4x than manual approach but follows separation of UI logic.

MvvmJS.UI.DataTemplate, declarative binding, auto placing in DOM

It is possible to go further and speed-up binding process with binding cache – binding process uses query selector to find all elements with data-win-bind attribute. I created a control, called MvvmJS.UI.DataTemplate which implements this logic and uses binding cache.

This approach is very simple and it’s slower only 3x than the manual approach but with full declarative binding and it wins for me. Especialy when the templates will be more complicated and it will be necessary to react on any data change.

Solution – MvvmJS.UI.DataTemplate

Usage of MvvmJS.UI.DataTemplate (UI/HTML part)

    <div id="dataTemplate">
        <div></div>
    </div>

Usage of MvvmJS.UI.DataTemplate (UI/code behind part)

                var cellTemplate = document.getElementById("dataTemplate");
                cellTemplate.winControl || WinJS.UI.processAll(cellTemplate);
                cells.forEach(function (cell) {
                    cellTemplate.winControl.render(cell, grid);
                });

DataTemplate class can be found in this project. MvvmJS project will be upgraded later (this month) with all new controls and logic.

Template Selector control


MvvmJS control: TemplateSelector

WinJS enables the developers to use declarative programming in UI layer. It fits very well with MVVM architectural style. The main idea is that UI (view which is HMTL part) can be managed by the javascript object ( ViewModel ). All of this works automatically thankfully to data-binding.

Example: lets have a HTML element wich is “bound” to ViewModel (JS object). Changes done in ViewModel can be reflected on HTML element, i.e. it can change a style, color, change a text inside, etc. Full example can be checked here

The idea can be extended a level higher. The idea is taken from WPF/Silverlight world, especially from Caliburn (as I worked with it for more than a year).

MvvmJS.UI.TemplateSelector control

The goal of this control is simple: selects a template for the databinding context object and then renders it with that template.

The common usage scenario is: let’s have ListView which displays messages and each message has a type. Each type contains different properties and is handled and rendered differently. Solution is simple.

Code behind part

    var elm = document.body;

    var list = new WinJS.Binding.List();

    list.push({ type: 'call', duration: 100 });
    list.push({ type: 'text', text: 'Hello world!' });
    list.push({ type: 'call', duration: 300 });
    list.push({ type: 'call', duration: 200 });
    list.push({ type: 'text', text: 'WinJS is cool!' });

    WinJS.UI.processAll(elm).then(function () {
        return WinJS.Binding.processAll(elm, { messages: list });
    });
    

The above code creates list of the messages and each message has a type (call, text). Message types have different properties. After filling the list we process all win controls within the document.body and then we run databinding process over it.

Rendering part

    <div id="messageTemplate" data-win-control="WinJS.Binding.Template">
        <div class="message" data-win-control="MvvmJS.UI.TemplateSelector" 
            data-win-bind="winControl.model:self MvvmJS.Binding.wbind"
            data-win-options="{ selector: {
		                            type: MvvmJS.UI.TemplateSelector.PropertySelector,
		                            property: 'type',
		                            pattern: '/default.html#{0}',
	                            } }">
        </div>
    </div>
    <div data-templateid="call" data-win-control="WinJS.Binding.Template">
        <div class="call">Call, duration <span data-win-bind="innerText:duration"></span>s</div>
    </div>

    <div data-templateid="text"class="message text" data-win-control="WinJS.Binding.Template">
        <div class="text">Text message: <span data-win-bind="innerText:text"></span></div>
    </div>

    <div id="listView"
        data-win-control="WinJS.UI.ListView"
        data-win-bind="winControl.itemDataSource:messages.dataSource"
         data-win-options="{ itemTemplate: messageTemplate }">
    </div>
    

There is a listview which gets the messages as an input. The template used for the rendering refers to a template with template selector control. Template selector control gets the message as the input (setting property model) and renders it. Template selector selects the template based on the property (setting selector option to PropertySelector class) “type” of the input object (in this case a message).

Templating

The templates are located in the file default.html and are identified by data-templateid attribute. Template selector uses template loading mechanism with caching capabilities. The templates are identified by “#”. For the above example, in case message is of ‘call’ type, then the pattern ‘/default.html#{0}’ will be replaced to ‘/default.html#call’ which identifies the template with data-templateid attribute ‘call’ in the file ‘/default.html’. The recommended approach is to store the templates in the separate file, i.e. templates.html.

The result

Just another example

Another common situation is just having a general “alert” dialog which gets an object as the input. Based on the object type it’s possible to choose appropriate template to render the message, i.e. exception, business messages, etc. In the traditional scenario it’s necessary to write Javascript code with ifs or switch/case and manualy inject HTML into UI.

Summary

The above mentioned problems are very common and they have very similar solution which I isolated into a control. The control is under development and there will be several enhancements added, i.e. animations. The complete example can be found on http://mvvmjs.codeplex.com/

Binding list and its projections

Binding list and its projections

General introduction

WinJS.Binding.List class was introduced into WinJS stack for providing “observable arrays” – a combinaton of Array API and the observable functionality. There is a documentation about WinJS.Binding.List here so I’ll focus on one its specific feature – projections.

WinJS.Binding.List class provides methods to create a view over its data. This view is called projection and there are two default projections:

  1. sorted list projection: it’s created by calling method list.createSorted(sortingFn)
  2. filtered list projection: it’s created by calling method list.createFiltered(sortingFn)

The projections are fully observable which means:

  • when an underlying list changes then the projection gets notification and updates itself
  • when a projection changes itself, it notifies others listeners about it

In addition the projection supports creating projection over projection and still keeping the same API as the underlying list – it implements a decorator pattern. This can create an interesting and useful combinations.

WinJS.Binding.List is mainly used to produce a data source object which is a primary input for WinJS.UI.ListView control. The same applies for the projections, too. This creates very common, powerful combination in real-world application scenarios.

Filtered combined with sorted list projections example

In the following example there is a underlying list which contains strings. Then from the list there is created sorted projection which creates a sorted view over underlying data. Then there is created filtered projection which filters strings starting with ‘b’. The result test is following:

        it("filtered over sorted projections", function () {
            var list = new WinJS.Binding.List();
            var sorted = list.createSorted(function (l, r) {
                return l.v.localeCompare(r.v);
            });

            var filtered = sorted.createFiltered(function (x) { return x.v[0] === "b"; });

            list.push({ v: "a" });
            list.push({ v: "b55" });
            list.push({ v: "c" });

            var item = list.getAt(0);
            item.v = "b0";
            list.notifyMutated(0);
            list.push({ v: "b99" });
            list.push({ v: "b44" });

            expect(filtered.getAt(0).v).toBe("b0");
            expect(filtered.getAt(1).v).toBe("b44");
            expect(filtered.getAt(2).v).toBe("b55");
            expect(filtered.getAt(3).v).toBe("b99");

        });
    

Common usage scernarios

Metro applications are based on the idea: “less is more” which means displaying less information but in more productive/usable way. A typical example is that there is one and only one underlying list of data (i.e. sales items) and the application displays them once on “hub” (an initial screen displaying the last 10 sales sorted by time), then on another screen displaying a subset of data ordered appropriately (comming from categories displaying only last 10 sales filtered for a category), etc.

The main idea is to load and build the list once, processing the changes to the underlying list once and automatically propagating them into all consumers, e.g. UI controls, list projections, etc. This can have great impact on the performance (less CPU sycles) ~ battery, developers productivity and maintenance.

Few bugs in projections but it’s getting better

WinJS.Binding.List and its projectios were introduced just before Win8 Beta version and there were several issue which I reported to Win JS team with appropriate fixes but you can start using it today. Just download the code from MvvmJS and reference bindingListExtensions.js. The project also includes the unit tests so all the functionality is fully tested.

Summary

WinJS.Binding.List and its projections are very useful and you can be very productive with them. As I used them, I encountered few scenarios where I had to create my own List projections by deriving from base list projections. I’ll write about them in next days.

Unfortunatelly list projections are “internal classes” but have quite stable API. I hope, WinJS team makes them publicly visible in WinJS package. There are some tricks how to over-come this issue but it’s just exceptional and I use it until they will be public (I hope it will be in RTM or final release build).

Binding extension functions (Part IV)

Binding extension functions

WinJS binding declaration offers binding customization via a custom binding method. There are several possibilities how to specify binding extension method.

A background info

The steps required for binding functions are:

  1. write a function meeting the following method signature:
    function (source, sourceProperty, dest, destProperty)
    

    The parameter names are self-explainable.

  2. make it publicly available from the global window object (example bellow exposes a function accessible as MvvmJS.Binding.localize)
  3. the binding function has to be marked “supported for processing” (it’s a requirement introduced by Win8 RC build). It can be done i.e. calling WinJS.Utilities.markSupportedForProcessing(fn)

Example

   WinJS.Namespace.define("MvvmJS.Binding", {
        localize: function (source, sourceProperty, dest, destProperty) {
            ......
        },
        .....
    });

    var markSupportedForProcessing = WinJS.Utilities.markSupportedForProcessing;
    Object.keys(MvvmJS.Binding).forEach(function (key) {
        markSupportedForProcessing(MvvmJS.Binding[key]);
    });

Extensions in action

Sample JS object

Let’s have the following Javascript class which will be used throug all samples.

    WinJS.Namespace.define("BindingExtensions.ViewModels", {
        SampleViewModel: MvvmJS.Class.define(function () {
            this.color = "red";
        }, {
            generateColor: function () {
                var colors = ['red', 'green', 'yellow'];
                var index = Math.ceil(Math.random() * colors.length-1);
                this.color = colors[index];
            }
        }, {
            color: {
                get : function () {
                    return this._color;
                },
                set : function (value) {
                    this._color = value !== null && value !== undefined && value.length === 0 ? "empty" : value;
                    this.colorRes = "color." + this._color;
                    this.richDescription = "This is rich multiline <BR> text. Selected color is <b>" + this._color + "</b>";
                    this.isGreen = value === "green";
                }
            },
            isGreen: null,
            colorRes: null,
            richDescription: null
            
        })
    });

In other words, there is a class SampleViewModel defined on namespace BindingExtensions.ViewModels. The class has for properties:

  • color: it’s accessible property (with get/set methods) which sets the rest properties based on sample dummy logic.
  • isGreen: it’s value property returning true in case color is ‘green’
  • colorRes: it’s value property containing a calculated resource key in form ‘color.{colorname}’.
  • richDescription: it’s value property and contains a dummy rich description with a color name.

Binding extension: localize

Usage:

<div class="value" data-win-bind="innerText:colorRes MvvmJS.Binding.localize"></div>

Explanation:
It reads the key (string) from colorRes property, use WinJS.Resources to translate it to user’s language and sets innerText of DIV element. It also rerun in case colorRes changes automaticaly out of the box.

Binding extension: style

Usage:

<div class="value" data-win-bind="backgroundColor:color MvvmJS.Binding.style">background color set to selected color</div>

Explanation:
It reads the color from the property and sets its value to backgroundColor on DIV’s style object. It handles color property changes automatically out of the box and rerun the binding.

Binding extension: urlStyle

Usage:

<div class="value" data-win-bind="backgroundImage:colorUri MvvmJS.Binding.urlStyle">background color set as background image</div>

Explanation:
It reads the colorUri from the property and sets its formatted value (form ‘url(value)’) to backgroundImage on DIV’s style object. It’s just a specific version of previous ‘style’ extension. Of course, it handles colorUri property changes automatically out of the box and rerun the binding.

Binding extension: toggleClass

Usage:

<div class="value" data-win-bind="WARNING:isGreen MvvmJS.Binding.toggleClass">text is capitalized in case the entered color is green</div>

Explanation:
It reads the boolean property isGreen from the data context object and it adds/remove (based on boolean property) the class WARNING on DIV’s class attribute. Of course, it handles property changes automatically out of the box and rerun the binding.

Binding extension: twoway

Usage:

<input type="text" class="value" data-win-bind="value:color MvvmJS.Binding.twoway"></input>

Explanation:
It activates two-way databinding between a property of the UI element and a property of the datacontext object. By default, the element’s properties are not observable. The only way to be notified about the property change is to handle an appropriate event depending on the UI control. MvvmJS comes with the two-way binding support for the following elements:

  • textbox: event ‘input’
  • checkbox: event ‘change’
  • more elements come later

In the above example, the text entered into the textbox (name of the color) is copied to property ‘color’ on the datacontext object and vice versa (from the object’s property to the textbox value).

Binding extension: unsafeHTML

Usage:

<div class="value" data-win-bind="innerHTML:richDescription MvvmJS.Binding.unsafeHTML"></div>

Explanation:
It reads the property richDescription from the data context object and it sets innerHTML of DIV. This operation (setting HTML property) is threaten as unsafe and throws security exception. If the content of the property is safe and it’s necessary to preserve the markup then it’s necessary to set innnerHTML through window.execUnsafeLocalFunction method. Of course, if a datacontext property changes, it automatically reruns the binding.

Binding extension: event

Usage:

<div class="button" data-win-bind="click:generateColor MvvmJS.Binding.event">click to generate color</div>

Explanation:
It binds onclick event raised by DIV element to the datacontext’s method generateColor. In addition ‘this’ object of event handler method generateColor is preserved (‘this’ is set to the datacontext object).

Summary

All binding extensions are included in the sample project BindingExtensions downloaded from MvvmJS codeplex project.


		

Observables and data-binding in action (Part III)

Observables and their usage in binding

The typical scenario where observables’ features are leveraged is data-binding (binding the observable objects to html element – in other words model/viewmodel to view).

Declaration syntax

WinJS establish data-binding to UI in the following form:

<div data-win-bind="targetPropertyChain:sourcePropertyChain [customBindingFunction]" >

This was a declaration with the following meaning:

  • targetPropertyChain: declares a target of the databinding. It’s property name on the HTML element. Example: innerText. It supports also the chain of the properties, e.g. winControl.content.
  • sourcePropertyChain: declares a source of the databinding. It’s property name chain on an object (also called databinding context) whose data are used for binding. Example: address.street, name, etc.
  • customBindingFunction: it’s an optional parameter and declares a custom databinding function which replaces the default databinding function. There are several examples of it developed in MvvmJS. WinJS comes with two binding functions:
    1. default: it’s default oneway databinding function which binds a property from databinding context into a property on HTML element initialy and any time property on context object changes.
    2. onetime: it’s the function which bind the property from databinding context into element only once and only once.

Usage examples

<div data-win-bind="innerText:name" >

It’s the most simple binding use-case and declares binding from datacontext.name to targetElement.innerText.

<div data-win-bind="VISIBLE:isEmpty toggleClass" >

This defines the binding with the custom binding function defined as an extension in MvvmJS. The binding function toggleClass adds class VISIBLE to the element CSS class attribute in case datacontext.isEmpty is true.

<div data-win-bind="innerText:person.homeAddress.street" >

This defines binding street of the home address of the person accessible as a property on datacontext object to the innerText property on the target HTML element.

<div data-win-control="MvvmJS.UI.TemplateSelector" data-win-bind="winControl.content:person" >

First, it declares control MvvmJS.UI.TemplateSelector control (a custom WinJS UI control) over DIV. Then there is a databinding of datacontext.person to content property of winControl attribute set on the target DIV element. Note: it’s usual practice/pattern that UI control sets attribute winControl on the element to control instance.

Data-binding in action

That was just the first part of the story: declaration. Now, lets make the databinding alive.

WinJS introduces WinJS.Binding.processAll(root, dataContext, ..other parameters..) method which:

  1. searches for any element with data-win-bind attribute on the HTML element tree starting with root (optionaly skipping root) and
  2. then process the binding declarations.

WinJS.Binding.processAll method is usually called from JS page or fragment file.

Example

(function () {
    "use strict";

    WinJS.UI.Pages.define("/views/dummyView.html", {
        element: null,

        ready: function (element, options) {
            this.element = element;
            element.winControl = this;
            this.options = options;

            var vm = new MvvmJS.Samples.DummyVieModel();
            WinJS.Binding.processAll(element, vm);
        },
    });
}());

The example above is code-behind of the view DummyView which runs the binding processing in the ready event handler (raised when the page is rendered and ready to be used). In the ready event it instantiates DummyViewModel (please note a convention DummyView ~ DummyViewModel).

In case of an enterprise application it would be better to generalize the approach and define a base class with calling the binding process method from its ready method (this also brings MvvmJS).

Property chain subscriptions

There is one very usefull feature of WinJS databinding. WinJS databinding leverage observables and adds there property chain subscription of any property in sourcePropertyChain.

Let’s explain it on the example in BDD (behavior driven development) style:
Given: there is the following binding declaration

<div data-win-bind="innerText:person.address.street" >

When: person OR address OR street changes

Then: the binding is reprocessed and div’s innertext contains new value. This is very usefull feature in complex scenarios.

Comparing to manual approach

In case of manual approach it would be necessary to:

  1. initialy read the property and set the HTML element property with the value
  2. subscribe to any property chain change and handle the it with setting the new value

Manual approach implies more boilerplate and repetitive code which increase complexity of the result JS code.

In the next part we will look into custom binding method and extensions introduced in MvvmJS.

WinJS Observables in Examples (Part II)

Non-obserserable class

In my previous part I wrote about Observable introduced in WinJS. It was more about what they are and how to define them better. In this part I’d like to explain their usage and all explained on examples. Let’s start with sample class:

    describe("non-observable class", function () {
        it("DTO class", function () {
            //arrange
            var Person = WinJS.Class.define(function () {
            }, {
                Name: null,
                Birthday: null,
                Age: null
            });

            var sut = new Person(); // sut = subject under test

            var events = [];
            // subscribes to any change in the property Name
            sut.bind("Name", function(newValue, oldvalue) {
                events.put(newValue);
            });

            //act
            runs(function () {
                sut.Name = "dummy person";
            })

            //assert
            waitsFor(function () { return event.length != 0 });

            runs(function () {
                expect(event.length)
            })
        })

The result is:

Observable DTO object

The previous example defines class Person which has three direct properties. The instances of this class do not inform the consumer about their changes and it’s not possible to subscribe to any changes there. In other words, we are not able to subscribe to any event.It’s just simple class (in this case also so called DTO class). In case of DTO classes (classes used as data holders), it’s possible to call WinJS.Binding.as(object) in order to transform them to observable.

        it("observable DTO instances ", function () {
            var events;
            runs(function () {

                //arrange
                //define  non-obserable class
                var Person = WinJS.Class.define(function() {
                }, {
                    Name: null,
                    Birthday: null,
                    Age: null
                });

                // create new class instance (object)
                var sut = new Person(); // sut = subject under test
                
                // transforms object into observable object
                sut = WinJS.Binding.as(sut);

                // subscribes to any change in the property Name
                sut.bind("Name", function(newValue, oldvalue) {
                    if(oldvalue !== undefined) {
                        events.push(newValue);
                    }
                });
                events = [];
                //act
                sut.Name = "dummy person";
            })

            waitsFor(function() { return events.length !== 0; })

            runs(function () {

                //assert
                expect(events[0]).toBe("dummy person");

            })

        })

In the above example there is class Person and class instance named ‘sut’. The class instance is then transformed into observable object (under the hood, sut is wrapped with dynamically generated observable wrapper). Then any change on the class property triggers the property change event. Subscription to the particular property change can be realized calling bind(propertyname, callback) method (more about it later).

Observable DTO class

Disadvantage of the above approach is that it’s necessary tranform every class instance to the observable version. In addition, it’s necessary to call property changes only via wrapper object ‘sut’ and not on the original object, otherwise no updates are raised. This is very common issue. Solution is using WinJS.Binding.define() method.

        it("defines observable DTO class", function () {
            var events;
            runs(function () {

                //arrange
                //define  non-obserable class
                var Person = WinJS.Binding.define({
                    Name: null,
                    Birthday: null,
                    Age: null
                });

                // create new class instance (object)
                var sut = new Person(); // sut = subject under test

                // subscribes to any change in the property Name
                sut.bind("Name", function (newValue, oldvalue) {
                    if (oldvalue !== undefined) {
                        events.push(newValue);
                    }
                });
                events = [];
                //act
                sut.Name = "dummy person";
            })

            waitsFor(function () { return events.length !== 0; })

            runs(function () {

                //assert
                expect(events[0]).toBe("dummy person");

            })

        })

The example above defines directly observable class Person. All class instances are then observable by default.

MVVM and Observables

That’s all fine but all works only on pure DTO classes. WinJS introduces observables especially for binding purposes. The best architecture model leveraging observables is M-V-VM (Model View ViewModel). The binding is used between V and VM – in other words, beween UI and ViewModel.

ViewModel has the following purposes:

  1. prepares data for View
  2. react to actions triggered from the View

ViewModel classes are full classes, not just DTO classes. ViewModel has properties (both access and value), methods (private, public), etc.

But WinJS-observabes has the following problems:

  1. it doesnt support observables on classes with accessible properties with getters/setters
  2. it wraps also methods into observables
  3. it’s not possible to define what properties are observable

The solution is using MvvmJS.Class.define(constructor, prototypeMembers, observableMembers, staticMembers). It defines normal class as with WinJS.Class.define but it adds few usefull capabilities:

  1. it enables us to specify (explicitly as third parameter) properties which we want to have with observable capabilities
  2. adds event capabilities (add/removeEventListener, dispatchEvent)

Fully observable class using MvvmJS.Class.define()


        it("defines observable full class", function () {
            var events = [];
            runs(function () {

                //arrange
                //define  non-obserable class
                var Person = MvvmJS.Class.define(function (name) {
                    // constructor  

                    this.Name = name;
                }, {
                    // non-observable members
                    Name: null,
                }, {
                    // observable members
                    Birthday: {
                        get: function () {
                            return this._birthday;
                        },
                        set : function (value) {
                            this._birthday = value;
                            this.Age = new Date().getYear() - this._birthday.getYear();
                        }
                    },
                    Age: null,
                });

                // create new class instance (object)
                var sut = new Person(); // sut = subject under test

                // subscribes to any change in the property Name
                sut.bind("Name", function (newValue, oldvalue) {
                    if (oldvalue !== undefined) {
                        events.push(newValue);
                    }
                });
                sut.bind("Birthday", function (newValue, oldvalue) {
                        events.push(newValue);
                });
                sut.bind("Age", function (newValue, oldvalue) {
                        events.push(newValue);
                });
                events = [];
                //act
                sut.Name = "dummy person";
                sut.Birthday = new Date(2000,1,1);
            })

            waitsFor(function () { return events.length > 1; })

            runs(function () {

                //assert
                expect(events[0]).toBe(12);
                expect(events[1].toString()).toBe(new Date(2000, 1, 1).toString());

            })

        })

There is the class Person with non-observable property Name and two observable properties (Age is value propety, Birthday is accessible (get/set) property). Setting Name doesn’t raise any notifications. Setting Birthday ends in setter method which sets the private _birthday property, calculates age and sets Age property. Both Age and Birthday properties trigger change notifications which are captured and stored in events array.

Using “propertychanged” event

I mentioned that MvvmJS.Class.define() adds also the event capabilities into the class in addition to notifications for binding. There are several reasons for this:

  1. when it’s necessary to be notified about the property change synchronously (immediately). By default the standard change property notifications (added by WinJS.Binding, also called binding notifications) are raised “asynchronously” – which means they are raised using setImmediate() function which queues the raising into the windows message queue. It’s good as Javascript engine has only one thread but sometimes it’s necessary to react immediately.
  2. when it’s better to have only one event and one event handler to handle any property change on the object. When using standard binding notifications added by WinJS it’s necessary to explicitly subscribe to each property change. So last example would then look like the following:
        it("defines observable full class with property change notifications", function () {

            //arrange
            //define  non-obserable class
            var Person = MvvmJS.Class.define(function (name) {
                // constructor  

                this.Name = name;
            }, {
                // non-observable members
                Name: null,
            }, {
                // observable members
                Birthday: {
                    get: function () {
                        return this._birthday;
                    },
                    set: function (value) {
                        this._birthday = value;
                        this.Age = new Date().getYear() - this._birthday.getYear();
                    }
                },
                Age: null,
            });

            // create new class instance (object)
            var sut = new Person(); // sut = subject under test

            var events = [];
            // subscribes to any change in the property Name
            sut.addEventListener("propertychanged", function (args) {
                var propertyName = args.detail;
                events.push(propertyName);
            });
            //act
            sut.Name = "dummy person";
            sut.Birthday = new Date(2000, 1, 1);

            //assert
            expect(events[0]).toBe("Age");
            expect(events[1]).toBe("Birthday");

        })

Summary

MvvmJS.Class.define() method enables us to define classes without any limitations, so it’s ideal to use it in M-V-VM architecture scenarios. Specifying observable properties explicitely has positive performance impact because overhead added due to observable capabilities is added only to required parts.

All examples can be downloaded from http://mvvmjs.codeplex.com/

Testing WWA apps with Jasmine on Windows 8

I work on a project which is WWA app and I must admit that:

  •  the code can quickly ends up in the mess,
  • the language itself is dynamic so there are no compile time errors (just runtime errors)

One of the ways how to ensure higher code quality is unit testing.

I paste here 2 vey important notes about unit testing from this blog because many people argue that they don’t have time to write unit tests OR it’s to advanced approach for them.

Testing is an advanced practice for the pros, not for me

My position is that whatever way you think of your process for writing code, you are testing it, e.g. by refreshing your browser(s) to verify that it is doing what it should. You are simply opting out of automating and improving your testing process, and in the long run (or even not-so-long run) you are spending more time hammering your browser’s refresh button than I spend writing tests that I can run today, tomorrow and next year should I so please.

Testing takes too much time, I’d rather just write production code

Both manual and automated testing takes time. But please, don’t spend an hour or two “evaluating” unit testing and/or TDD and then decide it is a waste of time. Unit testing and TDD are disciplines that need to be practiced just like any other. There is no way to get good at automated testing in a few hours. You need practice, and once you get there, then you will recognize the benefits I’m describing here, and then you will realize how much of a waste manual ad-hoc testing is. Besides, even if writing unit tests and testing your code rigorously takes a little more time, what would you prefer? To fail really fast, or to succeed?

Current situation

Unfortunatelly, there is no project template for unit testings of WWA apps in Visual Studio 2011. There are different projects templates for authoring WWA apps with VS 2011 but NO project template for unit testing and it’s a shame. We, inside Microsoft have the ways how to test WWA apps but they are not public.

The best would be to have a publicly available way how to test WWA apps with community behind.

Solution

First of all, there are some unit testing plugins into VS IDE like JustCode from Telerik or Unit testing plugin from JetBrains but no for running them as Metro WWA application.  So I had to invent my own solution. I had to port Jasmine runner including my own extensions in order to run the unit tests for WWA apps on Windows 8.

I use Jasmine as unit testing framework. I wrote a shell page (or so called test runner shell) which is set as the start page. The shell page runs the whole process which consist of:

  1. configuring Jasmine,
  2. discovering tests and
  3. running the tests upon user input.

In order to fit with Jasmine I had to write also a Jasmine reporter which communicates with the shell and reports the progress of tests execution.

Enought theory, example please.

I ported a referral example from Jasmine project and here is the result:

You can download the code from http://mvvmjs.codeplex.com It’s in the folder misc\SampleTests

How all this works:

There are two main things:

  1. all test files ends with *tests.js. It’s configurable via jasmine.wwa.fileFilter. Example: jasmine.wwa.testFilesFilter = “*spec.js”;
  2.  unit testing project is configured to start test runner shell file: shell.html.

The shell loads and run ALL test files. A test file itself registers test suite and specs into the jasmine environment. Please note that shell runner follows M-V-VM style.

Future development

The shell runner will be updated quite much as MvvmJS is going to be extended with different aspects, e.g. binding extenions, controls, etc.

If you want to use it on your project, just copy the whole project and add your tests – the shell will discover your tests and you will be able to run them.

Happy testing on WWA!