Learning JavaScript — Part 27

Jeff P
4 min readOct 31, 2022

--

Asynchronous calls and AJAX

Asynchronous code gets executed after “background” tasks are completed. For example, when we use the setTimeOut method, code will be executed, even though code after this may have already ran.

For example…

const firstMessage = function() {
setTimeout(function() {
console.log(`This function is called first, but displayed second`)
}, 5000);
};
const secondMessage = function() {
console.log("This function is called second, but displayed first");
};
firstMessage();
secondMessage();

which returns…

This function is called second, but displayed first
This function is called first, but displayed second

The firstMessage() function is asynchronous.

AJAX calls with XMLHttpRequest

This is the “old school” way of doing AJAX calls.

Firstly, we create a new object with the following:

const request = new XMLHttpRequest();

We then specify whether the call will be getting data (i.e. a GET request) and what the URL of the JSON data will be. JSON is simply a JavaScript object in text format.

So we specify the request with the “open” method….

const request = new XMLHttpRequest();
request.open("GET", "https://api.coindesk.com/v1/bpi/currentprice/BTC.json");

next we call the “send” method…

const request = new XMLHttpRequest();
request.open("GET", "https://api.coindesk.com/v1/bpi/currentprice/BTC.json");
request.send();

and finally we can make the JSON data load (asynchronously!) once we have retrieved it, with a load event used with addEvenListener and the “responseText” property.

const request = new XMLHttpRequest();
request.open("GET", "https://api.coindesk.com/v1/bpi/currentprice/BTC.json");
request.send();
request.addEventListener("load", function() {
console.log(this.responseText);
});

If it managed to retrieve the data, then it should display something like this in JSON…..

{"time":{"updated":"Oct 30, 2022 21:42:00 UTC","updatedISO":"2022-10-30T21:42:00+00:00","updateduk":"Oct 30, 2022 at 21:42 GMT"},"disclaimer":"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org","bpi":{"USD":{"code":"USD","rate":"20,677.3091","description":"United States Dollar","rate_float":20677.3091},"BTC":{"code":"BTC","rate":"1.0000","description":"Bitcoin","rate_float":1}}}

We can now convert this data to a true Javascript object so that we could use it….

const request = new XMLHttpRequest();
request.open("GET", "https://api.coindesk.com/v1/bpi/currentprice/BTC.json");
request.send();
request.addEventListener("load", function() {
const data = JSON.parse(this.responseText);
console.log(data);
});

which would now produce a real JavaScript Object….

If we open up bpi -> USD we can see the rate of Bitcoin….

So therefore we could reference this value in our newly-created “data” object we parsed from JSON….

const request = new XMLHttpRequest();
request.open("GET", "https://api.coindesk.com/v1/bpi/currentprice/BTC.json");
request.send();
request.addEventListener("load", function() {
const data = JSON.parse(this.responseText);
console.log(data);
console.log(`The current price of Bitcoin is ${data.bpi.USD.rate}`);
});

which returns…

The current price of Bitcoin is 20,688.6761

So we could reference anything pulled from this API… for example…

const request = new XMLHttpRequest();
request.open("GET", "https://api.coindesk.com/v1/bpi/currentprice/BTC.json");
request.send();
request.addEventListener("load", function() {
const data = JSON.parse(this.responseText);
console.log(data);
console.log(`The current price of Bitcoin is ${data.bpi.USD.rate} and the time the price was updated was at ${data.time.updated}`);
});

which returns….

The current price of Bitcoin is 20,653.8310 and the time the price was updated was at Oct 30, 2022 22:03:00 UTC

The “Fetch” API

The modern way of making asynchronous API calls, is to use fetch

If we compare the same request from the same URL used in the XMLHttpRequest example, we can see it is much simpler….

const request = fetch("https://api.coindesk.com/v1/bpi/currentprice/BTC.json");console.log(request);

which returns…

Promise {<pending>}

A “Promise” is basically a container object for a future value.

The benefit of Promises in JavaScript is that we no longer need to rely upon event handlers and callback functions like we did with XMLHttpRequest()

We can also chain promises!

Promises have different stages…. Before they have received a value, they will be “pending”. Once the value is received, the promise is “fulfilled”. Sometimes if the value cannot be received, it will show as “rejected”.

In order to retrieve the data we want (similar to the XMHttpResponse example) we need to use the .then property and the .json property, but even when we do this, we still need “return” this, and then to use the .then property once more as by using the .json property, this in itself creates another promise.

This is quite confusing, so it’s easier to show as code….

const request = function() { 
fetch("https://api.coindesk.com/v1/bpi/currentprice/BTC.json")
.then(function (response) {
return response.json();
console.log(response);
})
.then(function (data) {
console.log(data.bpi.USD.rate);
})
};
request();

So basically, we “fetch” the URL, then we use the .json property (which has now called ANOTHER promise, so we return it) and then we do something with that returned data.

This code can be shortened and tidied up a bit with arrow functions….

const request = () => { 
fetch("https://api.coindesk.com/v1/bpi/currentprice/BTC.json")
.then((response) =>
response.json()
)
.then((data) =>
console.log(`The price of Bitcoin is ${data.bpi.USD.rate}`)
)
};
request();

Handling (catching) errors

We can add a .catch option at the end of the chain to handle any errors when fetching data, such as for example if the data no longer exists or there is an issue with the URL itself.

// This works....
const request = () => {
fetch("https://api.coindesk.com/v1/bpi/currentprice/BTC.json")
.then((response) =>
response.json()
)
.then((data) =>
console.log(`The price of Bitcoin is ${data.bpi.USD.rate}`)
)
.catch((error) =>
alert("doesn't exist")
)
};
request();
// This doesn't....
const request = () => {
fetch("https://api.coindesk.com/v1/bpi/currentprice/ATC.json")
.then((response) =>
response.json()
)
.then((data) =>
console.log(`The price of Bitcoin is ${data.bpi.USD.rate}`)
)
.catch((error) =>
alert("doesn't exist")
)
};
request();

.finally

This comes after .then and .catch and will be called, whether the promise/s are fulfilled or not.

--

--

Jeff P
Jeff P

Written by Jeff P

I tend to write about anything I find interesting. There’s not much more to it than that really :-)

No responses yet