Tuesday, February 17, 2015

Chain Ajax Calls in Sequence Using jQuery Promise

"done" vs. "then" and a design pattern

Note:
Async programming for Ajax calls is a very common scenario, so this article will use Ajax as example in using Promise.
Comparing to parallel calls, make sequence call with promise are more complex and confusing.


jQuery2.0 $.when() Is not a Bad Choice

Many articles talk about the jQuery's implementation of promise is inadequate and is not compliant with Promise/A proposal, however
a. With my test of jQuery 2.0, I didn't notice the non-compliant issue mentioned in
http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semantics
b. According to this link, the performance of jQuery promise is even better than when.js http://complexitymaze.com/2014/03/03/javascript-promises-a-comparison-of-libraries/
c. Other promise library like when.js is not documented better than jQuery and its usage for browser requires the hassle to just run a build for browser version.
d. jQuery promise should meet most of the requirements for development for browser such as parallel loading, timeout, and sequence loading ...


done() vs. then()

When chaining multiple promises together, using done() is very different from then() even though both are executed after the promise is resolved. They serve very different purposes.
Basically to chain multiple promises as promise 1 -> promise 2 -> promise 3 ... in sequence, we have to use then to RETURN new promise to chain them together in "sequence".
If we just use "done()" or not RETURN a new promise from then(), then all calls will be executed immediately after the first promise 1 is resolved in the sequence of normal code execution which is a total miss of the point of promise.
In other words, in stead of

promise 1 -> promise 2 -> promise 3,
the execution will be
promise 1 ->
    promise 2, promise 3, promise 4 ...

promise 2, 3, 4 ... will only wait promise 1 and will executed all together without promise 4 wait for promise 3, and promise 3 wait for promise 2 ...

This is the complete code, pay attention to the comments

(function() {

    $(function () {

        var url1 = "http://api.census.gov/data/2013/pep/natstprc";
        var url2 = "http://api.census.gov/data/2013/pep/natstprc18";
        var url3 = "http://api.census.gov/data/2013/pep/monthlynatchar5";

        $.when($.ajax(url1)) // working with promise 1
            .done(function(data){ // working with promise 1, executed when promise 1 is available
                $('.myContent').append('<div>promise 1: ' + data[0].title + '</div>');
            })
            .fail(function(error){ // working with promise 1, executed when promise 1 fails
                $('.myContent').append('<div>promise 1: ' + error.statusText + '</div>');
            })
            .then(
                function(data) { // still working with promise 1, entering the promise 2 by returning promise 2
                    // use data to with the result of promise 1
                    // must return a new promise
                    return $.ajax(url2);
                },
                function()
                {
                    return $.ajax(url2); // to tolerate the failure of promise 1 and continue to promise 2
                }
            )
            .done(function(data){ // working with promise 2, if the first then doesn't return a new promise then here we will still work with promise 1
                $('.myContent').append('<div>promise 2: ' + data[0].title + '</div>');
            })
            .fail(function(error){ // working with promise 2, if the first then doesn't return a new promise then here we will still work with promise 1
                $('.myContent').append('<div>promise 2: ' + error.statusText + '</div>');
            })
            .then(
                    function(){ // working with promise 2, entering the promise 3 by returning promise 3
                        return $.ajax(url3);
                    },
                    function() // to tolerate the failure of promise 2 and continue to promise 3
                    {
                        return $.ajax(url3);
                    }
            )
            .done(function(data){ // working with promise 3
                $('.myContent').append('<div>promise 3: ' + data[0].title + '</div>');
            })
            .fail(function(error){ // working with promise 3
                $('.myContent').append('<div>promise 3: ' + error.statusText + '</div>');
            }); // add more then if necessary

    })
}());


Run the code, you will see the results shows in a sequence order.

promise 1: Population, Total - United States Of America
promise 2: United States: Population, female (% of total)
promise 3: United States: Population density (people per sq. km of land area)

To test the error handling, mess up the url2 and you will have result like


promise 1: Population, Total - United States Of America
promise 2: Not Found
promise 3: United States: Population density (people per sq. km of land area)


.then(
    function(data) { // still working with promise 1, entering the promise 2 by returning promise 2
        // use data to with the result of promise 1
        // must return a new promise
        return $.ajax(url2);
    },
    function()
    {
        return $.ajax(url2); // to tolerate the failure of promise 1 and continue to promise 2
    }
)

Notice that the above pattern tolerates the error from the promise 2 by returning a new promise in the "fail" function inside the "then()".

The readability of this code does not seem to much improvement over just using nested callbacks, but it helps to explain several pitfalls, such as using something like


.then(
    function(data) { 
         $.ajax(url2);
},

or


.then(
    function(data) {
         myAjaxcall();
    },

with which they fail in returning a new promise to make the chained sequence call happen.

Rewrite the above code using named functions instead anonymous functions will make the pattern much more clear and address the point of using promise.
(function() {

    var url1 = "http://api.census.gov/data/2013/pep/natstprc";
    var url2 = "http://api.census.gov/data/2013/pep/natstprc18";
    var url3 = "http://api.census.gov/data/2013/pep/monthlynatchar5";

    function getData1()
    {
        return $.ajax(url1);
    }

    function getData2()
    {
        return $.ajax(url2);
    }

    function getData3()
    {
        return $.ajax(url3);
    }

    function showData1(data)
    {
        var txt = data[0].title? data[0].title: '' + data.statusText? data.statusText: '';
        $('.myContent').append('<div>promise 1: ' + txt + '</div>');
    }

    function showData2(data)
    {
        var txt = data[0].title? data[0].title: '' + data.statusText? data.statusText: '';
        $('.myContent').append('<div>promise 2: ' + txt + '</div>');
    }

    function showData3(data)
    {
        var txt = data[0].title? data[0].title: '' + data.statusText? data.statusText: '';
        $('.myContent').append('<div>promise 3: ' + txt + '</div>');
    }

    $(function () {

        $.when(getData1()) // start of promise 1
            .done(showData1)
            .fail(showData1)

            .then(getData2, getData2) // start of promise 2 and tolerate error from promise 1
            .done(showData2)
            .fail(showData2)

            .then(getData3, getData3) // start of promise 3 and tolerate error from promise 3
            .done(showData3)
            .fail(showData3);
    })
}());

As you can see the chained promise pattern is much more clear.

References:

https://gist.github.com/domenic/3889970

http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semantics

http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt2-practical-use

http://tutorials.jenkov.com/jquery/deferred-objects.html (point is missing)

http://www.danieldemmel.me/blog/2013/03/22/an-introduction-to-jquery-deferred-slash-promise/

http://www.html5rocks.com/en/tutorials/es6/promises/

https://thewayofcode.wordpress.com/tag/jquery-deferred-broken/

http://www.maori.geek.nz/post/i_promise_this_will_be_short


Sunday, February 8, 2015

Set up React IDE with WebStorm9

 

This is a summary of steps to take to set up a React project in WebStorm 9.
 
This setup will enable instant JSX translation using React-tools and instant module packaging with Browserify (Watchify).
 
1. Download and Install WebStorm 9.0
2. Create React web project in WebStorm (Create a new folder)
3. Install package.json: npm init
4. Install Browserify: npm install -g browserify
5. Install watchify: npm install -g watchify
6. Install jQuery, react, bootstrap (and any other JavaScript libraries from npm)


npm install jquery --save
npm install react --save
npm install bootstrap --save

7Install react-tools from npm for JSX translation: npm install -g react-tools
8. Enable WebStorm Live Edit
9. Install JetBrains IDE Support for Chrome
10. Install React Developer Tools for Chrome
11. Go to
http://facebook.github.io/react/html-jsx.html for HTML to JSX converter. (optional for JSX development)

After coding is done: 
12. Run Browserify: browserify main.js -o all.js -d
13. Run JSX translation: jsx --watch src/ build/
14. Run Watchify: watchify main.js -o all.js -d
7. Use WebStorm Live Edit: must run in debug mode (not work very well with Watchify and JSX translation)

Tuesday, February 3, 2015

Page rendering performance of jQuery vs Knockout vs React vs Riot2


Here is an interesting performance test result which compares the rendering speed of jQuery, Knockout and React at page load.

This is not a test of an event that triggers an update to page which in theory the virtual DOM of React should stand out.

Rendering 10000 rows of single column table.


IE 11
Chrome
Safari
jQuery
6.5 s
0.8 s
0.7 s
Knockout
8.5 s
4.0 s
3.3 s (30s the UI actually show up)
React
1.3 s
0.6 s
1.0 s
D3
1.7 s
0.2 s
0.2 s
Riot2
14 s
3.9 s


You can see that Chrome beats IE11 in all cases and React beats the other two. It is interesting to see that jQuery runs almost as fast as React in Chrome.

Update: I tested Safari. It is comparable to Chrome but with Knockout, the program recorded that the running of code was done in 3 seconds but it actually doesn't show up in the browser for 30 seconds.

Monday, February 2, 2015

What is one-way data binding in React?


As a JavaScript developer who has a lot of experience with jQuery but new to frameworks like Knockout or Angular, when React emphasizes it is a one-way data binding vs two-way data binding of the other two frameworks, I was kind of confused.

React: "React implements one-way reactive data flow which reduces boilerplate and is easier to reason about than traditional data binding"

After a few more reading, actually it is dead simple. One-way data binding is just about not doing something than about doing something.

Let's use jQuery as example to explain what it is. Let's start with a zero-way data binding or no data binding at all.

Zero-way data binding

It is just HTML with no script.

<input class="myInput" type="text" />

 
no script, no data binding. Isn't that simple?
 
One-way data binding
<input class="myInput" type="text" />
<script>
    var data = 'hello world';
    $('.myInput').val(data)
</script>
When the script runs, it one-way initializes the HTML control to a value.

Two-way data binding
<input class="myInput" type="text" />
<script>
    var data = 'hello world';
    $('.myInput').val(data);
    $('.myInput').onchange(function(){
        data = $(this).val();
        //update any other 1000 controls who uses data too    })
</script>
As you can see, after the one-way initializing the input control, the "onchange" event handler updates the data and other 1000 controls who use the data. This the 2nd direction of data flow: from UI to data.

React's Data Binding

The confusion I had is that why they are all saying React is one-way data binding, when definitely you can use same event handler to implement two-way data binding. It turns out that it is called so just because you have to implement two-way binding by code explicitly instead of implicitly as in the other frameworks.

So this React's one-way data binding
var SearchBox = React.createClass({
    getInitialState: function(){
      return {currInput: 'hello world'}
    },    
    render: function(){
        var currInput = this.state.currInput;
        return (
            <div>
                <input type="text" value={currInput} />
                <div>{currInput}</div>
            </div>
        );
    }
});

React.render(<SearchBox />, $('.myContent')[0])
 
The HTML controls are initialized with the state/data at one direction. The reason it is not two-way yet is just that we haven't implement anything that will flow data from UI to state/data.

React's "two-way data binding"

var SearchBox = React.createClass({
    getInitialState: function(){
      return {currInput: 'hello'}
    },
    handleKey: function(e)
    {
        this.setState({currInput: this.state.currInput + e.key });
    },
    render: function(){
        var currInput = this.state.currInput;
        return (
            <div>
                <input type="text" value={currInput} onKeyPress={this.handleKey} />
                <div>{currInput}</div>
            </div>
        );
    }
});

React.render(<SearchBox />, $('.myContent')[0])
Call this code "two-way" is kind of misleading. When you have to do something explicitly by code, it is not "two-way". It is still one way because "two-way" means two direction data flow automatically implicitly by framework. When you have do it by code, it is "your way" not "two-way". Stop playing the word game! :-)

Why it is good?

It is good just because it falls in the pattern that "less unknown is good when complexity grows". When the framework doing a lot for you automatically, implicitly in a big application, you will get lost. For a simpler application, it is just great since you write fewer code.

For example:

return (
    <div>
        <input type="text" value={currInput} onKeyPress={this.handleKey} />
        <div>{currInput}</div>
        <div>{currInput}</div>
        <div>{currInput}</div>
        <div>{currInput}</div>
        <div>{currInput}</div>
        // a 1000 div use currInput        <div>{currInput}</div>
    </div>
);
Here the beauty is that we have to write a 1000 lines of <div> to clearly say that another 1000 controls will be affected.

Why the other framework's two-way binding is bad?

<head>
    <title>Observable 2</title>
    <script src="Scripts/jquery-1.11.0.min.js"></script>
    <script src="Scripts/knockout-3.2.0.js"></script>
    <script>
        function myViewModel1() {
            this.myData1 = ko.observable('hello world');
        }
 
        $(function () {
            ko.applyBindings(new myViewModel1());
        });
    </script>
 
</head>
<body>
    <input data-bind="value: myData1, valueUpdate: 'keyup'" />
    <input data-bind="value: myData1, valueUpdate: 'keyup'" />
    <input data-bind="value: myData1, valueUpdate: 'keyup'" />
    <input data-bind="value: myData1, valueUpdate: 'keyup'" />
    // could have 1000 input anywhere in the page
    <input data-bind="value: myData1, valueUpdate: 'keyup'" />
 
    <div class="myDiv" data-bind="text: myData1"></div>
    <div class="myDiv" data-bind="text: myData1"></div>
    <div class="myDiv" data-bind="text: myData1"></div>
    <div class="myDiv" data-bind="text: myData1"></div>
    <div class="myDiv" data-bind="text: myData1"></div>
    // could have 1000 div anywhere in the page
    <div class="myDiv" data-bind="text: myData1"></div>
</body>

As you can see the two-way data binding of Knockout make things are so simple, only a few lines of JavaScript codes are needed to bind a few thousands of controls all together to a single data.

Any input can take a change and the change is made automatically to the other few thousands controls.

This is bad because in a large app, it really hard to keep track where are all these thousands of controls and data flow is a mess.

The power of two-way binding.

With this sample, you can feel the power/mess of two-way data bind of knockout. Typing in any of the input box will change anything else on the page. Imagine this a large single page application with controls everywhere.



http://facebook.github.io/react/docs/two-way-binding-helpers.html
http://n12v.com/2-way-data-binding/

Why React?


Why React?

Why did we build React?

React.js and How Does It Fit In With Everything Else?

"If you break down your application into smaller components (main menu, footer, list, list item, datepicker, etc.) then it becomes easier to imagine building a complex application and it remaining maintainable. This is the promise of component-based architectures. Essentially it is jQuery plugins but standardized and better encapsulated"

ReactJS For Stupid People - Andrew Ray's Blog

Flux for Stupid People

"Componentized UI is the future of web development, and you need to start doing it now"


React vs Angular Performance:

http://www.williambrownstreet.net/blog/2014/04/faster-angularjs-rendering-angularjs-and-reactjs/

http://mono.software/posts/Improving-AngularJS-long-list-rendering-performance-using-ReactJS/

https://www.codementor.io/reactjs/tutorial/reactjs-vs-angular-js-performance-comparison-knockout

https://www.codementor.io/reactjs/tutorial/react-vs-angularjs


React Sites:

http://feedly.com/i/spotlight/javascript

Saturday, January 31, 2015

React Programming Pitfalls


1. When returning JSX from "render", the following ( cannot be on next line. Otherwise the following error will be thrown in browser debug console.

Invariant Violation: SearchBox.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

$(function(){
    var SearchBox = React.createClass({
        getInitialState: function(){
          return {currInput: ''}
        },
        handleKey: function(e)
        {
            this.setState({currInput: this.state.currInput + e.key });
        },
        render: function(){
            return (                <div>
                    <input type="text" onKeyPress={this.handleKey} />
                    <div>{this.state.currInput}</div>
                </div>
            );
        }
    });

    React.render(<SearchBox />, $('.myContent')[0])
})

2. React event name is case sensitive, WebStorm intellisense's event name is all lower cases.

render: function(){
    return (
        <div>
            <input type="text" onKeyPress={this.handleKey} />
            <div>{this.state.currInput}</div>
        </div>
    );
}

Set up React IDE with WebStorm 9.0


Set up React IDE with WebStorm 9.0

   Download and Install WebStorm

   Create an empty project in WebStorm

   Install React Developer Tools for Chrome

To Enable Instant Browser Update

   Enable WebStore Live Edit
   Install JetBrains IDE Support for Chrome

To convert HTML to JSX

   Go to http://facebook.github.io/react/html-jsx.html for HTML to JSX converter.

To compile jsx into JavaScript

   Install react-tools from npm for jsx translation
 
   > npm install -g react-tools
   > jsx --watch src/ build/