Writing asynchronous code

ES5 natively supports two patterns for writing the asynchronous code, that is, the event pattern and the callback pattern. While writing the asynchronous code, we usually start an asynchronous operation and register the event handlers or pass the callbacks, which will be executed once the operation is finished.

The event handlers or the callbacks are used, depending on how the specific asynchronous API is designed. An API that is designed for an event pattern can be wrapped with some custom code to create the callback pattern for the API, and vice-versa. For example, AJAX is designed for the event pattern, but jQuery AJAX exposes it as a callback pattern.

Let's consider some examples of writing asynchronous code involving events and callbacks and their difficulties.

The asynchronous code involving events

For asynchronous JavaScript APIs involving events, you need to register the success and error event handlers which will be executed depending on whether the operation was a success or failure respectively.

For example, while making an AJAX request, we register the event handlers which will be executed depending on whether the AJAX request was made successfully or not. Consider this code snippet which makes and AJAX request and logs the retrieved information:

function displayName(json)
{
  try
  {
    //we usally display it using DOM
    console.log(json.Name);
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}
function displayProfession(json)
{
  try
  {
    console.log(json.Profession);
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

function displayAge(json)
{
  try
  {
    console.log(json.Age);
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

function displayData(data)
{
  try
  {
    var json = JSON.parse(data);

    displayName(json);
    displayProfession(json);
    displayAge(json);
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

var request = new XMLHttpRequest();
var url = "data.json";

request.open("GET", url);
request.addEventListener("load", function(){
  if(request.status === 200)
  {
    displayData(request.responseText);
  }
  else
  {
    console.log("Server Error: " + request.status);
  }
}, false);

request.addEventListener("error", function(){
  console.log("Cannot Make AJAX Request");
}, false);

request.send();

Here, we assume the data.json file to have this content:

{
  "Name": "Eden",
  "Profession": "Developer",
  "Age": "25"
}

The send() method of the XMLHttpRequest object is executed asynchronously, which retrieves the data.json file and calls the load or error event handler, depending on whether the request was made successfully or not.

There is absolutely no issue with how this AJAX works, but the issue is with how we write the code involving events. Here are the issues that we faced while writing the previous code:

  • We had to add an exception handler for every block of code that will be executed asynchronously. We can't just wrap the whole code using a single try…catch statement. This makes it difficult to catch the exceptions.
  • The code is harder to read, as it's difficult to follow the code flow due to the nested function calls.
  • If another part of the program wants to know if the asynchronous operation is finished, pending, or being executed then we have to maintain the custom variables for that purpose. So we can say it is difficult to find the state of the asynchronous operation.

This code can get even more complicated and harder to read if you are nesting multiple AJAX or any other asynchronous operations. For example, after displaying the data, you may want to ask the user to verify if the data is correct or not and then send the Boolean value back to the server. Here is the code example to demonstrate this:

function verify()
{
  try
  {
    var result = confirm("Is the data correct?");
    if (result == true)
    {
      //make AJAX request to send data to server
    }
    else
    {
      //make AJAX request to send data to server
    }
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

function displayData(data)
{
  try
  {
    var json = JSON.parse(data);

    displayName(json);
    displayProfession(json);
    displayAge(json);

    verify();
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

The asynchronous code involving callbacks

For asynchronous JavaScript APIs involving callbacks, you need to pass the success and error callbacks, which will be called depending on whether the operation was a success or failure respectively.

For example, while making an AJAX request using jQuery, we need to pass the callbacks, which will be executed depending on whether the AJAX request was made successfully or not. Consider this code snippet that makes an AJAX request using jQuery and logs the retrieved information:

function displayName(json)
{
  try
  {
    console.log(json.Name);
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

function displayProfession(json)
{
  try
  {
    console.log(json.Profession);
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

function displayAge(json)
{
  try
  {
    console.log(json.Age);
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

function displayData(data)
{
  try
  {
    var json = JSON.parse(data);

    displayName(json);
    displayProfession(json);
    displayAge(json);
  }
  catch(e)
  {
    console.log("Exception: " + e.message);
  }
}

$.ajax({url: "data.json", success: function(result, status, responseObject){
    displayData(responseObject.responseText);
}, error: function(xhr,status,error){
    console.log("Cannot Make AJAX Request. Error is: " + error);
}});

Even here, there is absolutely no issue with how this jQuery AJAX works, but the issue is with how we write the code involving callbacks. Here are the issues that we faced while writing the preceding code:

  • It is difficult to catch the exceptions, as we have to use multiple try and catch statements.
  • The code is harder to read, as it's difficult to follow the code flow due to the nested function calls.
  • It's difficult to maintain the state of the asynchronous operation.

Even this code will get more complicated if we nest the multiple jQuery AJAX or any other asynchronous operations.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.253.163