Praveen Singh

Handling Asynchronous Javascript using Deferred and Promise

Introduction


HANDLING ASYNCHRONOUS JAVASCRIPT AND FOUNDATION OF DEFERRED AND PROMISE.

Promise api provides standard and publicly open api for working with asynchronous operations, such as Ajax. In its simplest form, it waits until a later time to perform an action. essentially, you're deferring the action until a prior action is completed. Ajax is one such situation, We don't want to take some actions until we know that the server has successfully sent information back to us. Being able to wait for that returned value is key. Callbacks can be used to solve the same problem, however it leads to nesting, which some time go very deep.

Step by step video explanation


What we are solving?


Lets first see few example of asynchronous process in javascript

a Ajax based Asynchronous operation.

            
// a Ajax based Asynchronous operation
xhr('/api/login', function(user) {

    //Callback handler
    
});
            

a Timeout based Asynchronous operation.

            
// a Timeout based Asynchronous operation
setTimeout(function(user) {

    //Callback handler
    
}, 1000);
            

Both the above example are asynchronous, because we don't know when the callback handler will get called.

Yes, setTimeout says that 1 sec....but believe me, it actually just say that callback will be called after minimum 1 sec. It may get called after 1 sec, but if the main thread of javascript engine is occupied with something(could be a infinite for loop), it will never get called.

So at this stage, it is very important to understand, How javascript engine handles an asynchronous process.

How Asynchronous Javascript process works?

Follow black arrow and callouts for details

What's going on here?

  1. Javascript execution start in single thread.
  2. When it finds a block task like setTimeout or Ajax, it pass it to asynchronous flow which handled by Browser or Javascript engine
  3. Asynchronous task wait for blockage to resolve, in setTimeout, when delay get over or in case of Ajax, when server return the response.
  4. Post that, it find out any callback handler link with it. It it is present, it passed to Javscript engine Event queue.
  5. Reaching to queue is no guarantee of execution, Event queue wait of Main thread to get free, once it get the slot it push the callback handlers one by one

Let's touch Promise and Deferred now


Difference (and similarities) between Promise and Deferred

Before we go further, it is important to clear out the difference in these buzz words

Promise

Promise represents public apis, which let you handle asynchronous process by uniform format. It also let you nest the task, in sequential order, to perform

In general, Promise can be in below states

  1. pending: initial state, not fulfilled or rejected.
  2. fulfilled: successful operation
  3. rejected: failed operation.

Deferred

Deferred can be seen as wrapper over Promise or utility for Promise, which let play with state of Promise

In another words, A Deferred is just a Promise with methods that allow its owner to resolve or reject the Promise

Now, since we know how Javascript engine handle Asynchronous process, lets look on the Promise api

The ajax example we discussed at starting, can easily be solved by below code using Promise and Deferred

A sample solution using Promise.

Assume that defXhr is a Promise/Deferred based xhr

defXhr("/login").then(function(user) {
    ////Callback handler
})

        

Let's complicate things...

At this stage Promise may not look very promising, let's complicate the situation further.

Take below real world problem

  1. You need to develop a home page of e-shopping site.
  2. first you have to take login credential from user, make a server call for authentication.
  3. On successful authentication, show greeting message for user.
  4. Show loading icon in main section.
  5. Make a server call to show home page with “Top Products”
  6. Once it is done, take a server call to get “Deals of the day”, and show on the right side of home page.
  7. Once it is done, get the information of last product user had purchased from site and show the pop up, “do you want to review this product?”

Solution using callback.

            
xhr('/api/login', function(user) {
    showGrretings();
    showLoadingIcon();
    xhr('/topproducts', function(products) {
        showProducts();
        xhr('/dealOfTheDay', function(products) {
            showDealOfTheDay();
            xhr('/reviewLastPurchaseProduct', function(products) {
                showRevieDialog();
            });
        });
    });
});

        

In above case, more the level of nesting, the harder the code is to read, debug, maintain, upgrade, and basically work with. This is generally known as "callback hell" or "Pyramid of Doom".

Also, if we needed to handle errors, we need to possibly pass in another function to each xhr call to tell it what it needs to do in case of an error.

If we wanted to have just one common error handler, that is not possible.

Solution using Promise.

defXhr("/login").then(function(user) {
    showGreatings(user);
}).then(function() {
    return request("/topproducts");
}).then(function(products) {
    showProducts(products);
}).then(function(data) {
    return request("/dealOfTheDay");
}).then(function(dealOfTheDay) {
    showDealOfTheDay(dealOfTheDay);
}).then(function(data) {
    return request("/feedback");
}).then(function(purchasedProduct) {
    showFeedback(purchasedProduct);
});

        

In above example, each request will make server calls. Each server will return returns a promise, and we use the then function to add a success handler.

Every time a success handler return a promise, it force execution to wait before another server call. Also, the server response value for that promise will be passed as an argument to the next success handler in the chain.

How Asynchronous Javascript process works with Deferred and Promise?

Follow black arrow and callouts for details, it is similar to the diagram we discussed before, with the twist of Deferred.

Life cycle of Deferred and Promise?

Follow black arrow and callouts for details

Let's touch the real code now...


Core javascript doesn't provide Promise api. However it is so cool, It's implementation provided by many Javascript framework and Engine

Famous are jQuery, Dojo, Angular, etc

Javascript engine like Nodejs's V8 engine also provide implementation of these apis.

I am providing the real code from different framework(which looks and behave same, as they are implementation of public api of Promise), you can opt from below articles, which one you are looking for.

Note: i will add more and more article in below section as and when i get the time.


Contact Me


If you want to contact me for feedback or suggestion or doubt. You can do so by commenting on Blogger article or in Youtube comments section.

You can also approach me dropping me mail directly at mails.icodingclub@gmail.com

3 comments: