The Evolution of Asynchronous Actions in JavaScript

Evan Greer
3 min readAug 10, 2020

--

A promise eventually settled

In this blog post, I will explore the evolution of handling asynchronous actions in JavaScript. An asynchronous action refers to an action that runs while allowing the computer to move on to other tasks while waiting for the asynchronous action to complete. An example of an asynchronous action is making a network request.

Javascript originally used callback functions to handle asynchronous actions. The issue with this was this structure encouraged the use of nested code that became hard to deal with. With the introduction of ES6, integrated native promises were introduced allowing for significantly more readable code. ES8 then introduced the async…await syntax. In this blog post, I will specifically look at the changes in the syntax for a HTTP POST request to illustrate the evolution in handling asynchronous actions.

What is a Promise?

In Javascript, a promise is an object that represents the eventual outcome of an asynchronous operation. A promise can have one of three states: pending, fulfilled, and rejected. The pending state is when the operation has not been completed. The fulfilled state is when the operation has been completed and the promise now has a resolved value. The rejected state is when the operation has failed. All promises eventually settle.

Making a GET Request using the XHR object

A GET HTTP request retrieves information from a source. JavaScript runs GET requests asynchronously by allowing the request to be handled in the background while JavaScript continues to run other actions. JavaScript uses an event loop to handle asynchronous function calls. Function calls are added to a stack. Functions that make requests need to wait for servers are sent to a separate queue. The functions in the stack are executed then the functions in the separate queue are executed. This allows for a smoother browser experience for the user.

The following code is used for making a GET Request. The XMLHttpRequest API is used in this code to make the GET Request.

const xhr = new XMLHttpRequest();
const url = 'http://api-to-call.com/endpoint';
xhr.responseType = 'json';
xhr.onreadystatechange = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
// Code to be executed
}
};
xhr.open('GET', url);
xhr.send();

The code above represented the boilerplate code for making a HTTP GET request before the introduction of native promises in ES6.

Making GET HTTP Requests Using Native Promises

The introduction of promises in ES6 made event handling easier. The fetch API is used to handle requests using promises. The boilerplate code for the GET Request using the fetch API is as follows:

fetch('http://api-to-call.com/endpoint').then(response => {
if (response.ok) {
return response.json();
}
throw new Error('Request failed!');
}, networkError => console.log(networkError.message)
).then(jsonResponse => {
//Code to execute with jsonResponse
});

The use of fetch calls and promise chaining allows requests to become more readable. The introduction to async…await syntax in ES8 increased the reability.

Making a GET Request using Async-Await Syntax

With ES8, a new syntax was introduced for handling asynchronous actions. This new syntax allows for asynchronous code to read similarly to traditional code. The syntax does not introduce new functionality but rather greatly improves readability. The async keyword is used to write the function that handles asynchronous actions. The async function always returns a promise. The await keyword is used to return the resolved value of a promise. It halts the execution of the async function until the promise is resolved. Using the async-await syntax, the boilerplate code for the GET Request becomes:

async function getData() {
try {
const response = await fetch('https://api-to-call.com/endpoint');
if (response.ok) {
const jsonResponse = await response.json();
//Code to execute
}
throw new Error('Request Failed!');
} catch(error) {
console.log(error);
}
}

The use of async-await syntax makes the writing of the GET request incredibly readable. This block of code clearly shows that the code is awaiting the fetch call to get executed. If the response comes by ok, execute the code. If an error is throw, display the error to the console.

Conclusion

In conclusion, the evolution of the GET request from using the XHR object to using the fetch API and promise chaining to using the async-await syntax shows the development of JavaScript to a more readable syntax. I would like to acknowledge Codecademy as the basis for this blog post.

--

--

Evan Greer
Evan Greer

Written by Evan Greer

Flatiron School Software Engineering Immersive Graduate, Denver, Colorado

No responses yet