Sunday, November 12, 2017

Javascript & Asynchronous programming

Async programming in Javascript 

Asynchronous programming provides superior performance compared to synchronous programming. 
And with the promises it's now very easy to do async programming in ES6.

Whats Is Really Async Programming ?

A good analogy to describe what async programming is ,  would be:
We have  a cook who doesn't start any  task before the previous task is finished . He gets a pizza order and then a french fries order. After he prepares the pizza and puts it into the oven he doesn't do anything until pizza is baked, which means he has a lot of idle times between tasks . This is synchronous way of working.

On the other hand we also have an async cook  who uses timer for  tasks and keeps switching between tasks to prevent idle time , he prepares the pizza into the oven, in the mean time he puts the french fries into the fryer and so on.

Obviously async cook will be utilizing his time much more efficiently and finishing  orders much quicker.
Sync Cook :
|Make pizza|Fry French Fries|Cook Omelette|
Async cook:
|Make pizza|Cook Omelette|
   |Fry French Fries

In programming we use async programming technique  to utilize idle time which happens during a  time consuming task, this task can be calls to web services or databases or something else .
During the async call  we can do other things until the result comes back, the execution flow will not be  blocked (unlike sync calls). All this can be done using promises.
Below is a sample javascript code which is using then() function (that's how we consume promises).(Here you need to send  your own API Key as "APPID" , which you can get for free from https://openweathermap.org/api.)
1:   var url = "http://api.openweathermap.org/data/2.5/";  
2:    var city = "New York";  
3:    var appID = "XX";  
4:    var commonParam = "?APPID=" + appID + "&q=" + city + "&units=imperial";  
5:    var urlWeather = url + "weather" + commonParam;  
6:    var promiseToCallWeatherApi = $.ajax({  
7:      url: urlWeather, dataType: 'json'  
8:    });  
9:    promiseToCallWeatherApi  
10:      .then(function (resultWeather) {  
11:        console.log("Temperature is: " + resultWeather.main.temp);  
12:      })  
13:      .catch(function (err) {  
14:        console.log("An error occurred getting weather info" + err);  
15:      })  
16:    console.log("Getting weather info..");  

The code calls a web service which provides weather info (line 9)
The response can  take less than a second time and in the mean time we want to show some message on the screen(line 16) and finally we want to show the result when it comes back (line 11). And if the call fails we want to show an error message (line 13-15)
Below is the result screen:
As mentioned above async call  did not  block the execution and that's why the "Getting weather info" is displayed first which means line 16 is executed before the entire block of 11-14. First it made the api call on line 9, then executed line 16 , waited for the result and displayed the result after its done (line 11).

We can also chain multiple then () functions, which basically means : do this, then this then that..


1:    var url = "http://api.openweathermap.org/data/2.5/";
2:    var city = "New York";  
3:    var appID = "xx";  
4:    var commonParam = "?APPID=" + appID + "&q=" + city + "&units=imperial";  
5:    var urlWeather = url + "weather" + commonParam;  
6:    var promiseToCallWeatherApi = $.ajax({  
7:      url: urlWeather, dataType: 'json'  
8:    });  
9:    promiseToCallWeatherApi  
10:      .then(function (resultWeather) {  
11:        console.log("Temperature is: " + resultWeather.main.temp);  
12:      })  
13:      .then(function (result) {  
14:        console.log("Enjoy the weather!");  
15:      })  
16:      .catch(function (err) {  
17:        console.log("An error occurred getting weather info" + err);  
18:      })  
19:    console.log("Getting weather info..");  
The result is:

We can also make multiple api calls:
1:   var urlForecast = url + "forecast" + commonParam;  
2:    var promiseToCallWeatherApi = $.ajax({  
3:      url: urlWeather, dataType: 'json'  
4:    });  
5:    var promiseToCallForeCastApi = $.ajax({  
6:      url: urlForecast, dataType: 'json'  
7:    });  
8:    promiseToCallWeatherApi  
9:      .then(function (resultWeather) {  
10:        console.log("Temperature is: " + resultWeather.main.temp);  
11:      })  
12:      .then(function (result) {  
13:        return promiseToCallForeCastApi;  
14:      })  
15:      .then(function (resultForeCast) {  
16:        console.log("Forecast's first result is:" + JSON.stringify(resultForeCast.list[0].main));  
17:      })  
18:      .catch(function (err) {  
19:        console.log("An error occurred getting weather info" + err);  
20:      })  
21:      .then(function (result) {  
22:        console.log("Enjoy the weather!");  
23:      })  
24:    console.log("Getting weather info..");  

The result is as below:
In the above I had to return the result of the call in line 13 so that the next then() function in the chain (line 15) will get the result as a parameter(resultForeCast).

The catch block above is applicable to both the then() functions . 
 So to identify where the error happened you can create some if else statements  inside the catch block and handle different type of errors .