JavaScript: Promise w/ setTimeout()
, XMLHttpRequest
and fetch()
A JavaScript Promise object allows us to perform asynchronous tasks, representing its eventual value.
Promises became available in JavaScript as part of the ECMAScript 6 (ES6) specification.
We begin by creating an instance of the Promise
constructor, to which an anonymous function is passed. The anonymous function takes two parameters - the resolve()
and reject()
methods. Async operation goes inside the anonymous function, which on success calls resolve()
, else invokes reject()
.
The syntax generally looks as follows:
if(window.Promise) {
var promise = new Promise(function(resolve, reject) {
if(/*async operation success*/) {
resolve('Success');
}
else {
reject('Fail');
}
});
promise.then(function(response) {
console.log(response);
}, function(error) {
console.log(error);
});
}
Two methods are availed on instantiation of the promise
object, the then()
and the catch()
methods. The then()
method takes two callback functions as its arguments: the first function is called when the promise is fulfilled, and the second when the promise is rejected. Both functions have one argument: a fulfilment value previously passed to resolve()
for the first function and a reason of rejection passed to reject()
for the second function. The catch()
method also handles rejection
promise.then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
});
but it will not be executed if the second function inside the preceding then()
is present. Invoking catch()
is also equivalent to calling then(undefined,function)
as shown below
promise.then(function(response) {
console.log(response);
}).then(undefined, function(error) {
console.log(error);
});
In this tutorial, we will explore (with examples) how to use the setTimeout()
method and the XMLHttpRequest
object with JavaScript Promise; and lastly, the Fetch API
which uses Promises.
Promise with setTimeout()
The isEven()
method below creates a promise on call of it using the setTimeout()
function. The created promise will resolve if the argument passed to isEven()
is an even number (as the number 12, below), else it gets rejected.
if(window.Promise) {
function isEven(n) {
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
if(n%2 == 0) {
resolve(n + ' is an even number');
}
else {
reject(n + ' is an odd number');
}
}, 1500);
});
return promise;
}
isEven(12).then(function(response) {
console.log(response);
}, function(error) {
console.log(error);
});
}
The resolved value gets printed into the browser's console as:
12 is an even number
Promise with XMLHttpRequest
Object
Here, we will show how to use a promise to resolve/reject the outcome of an XMLHttpRequest.
We will retrieve some details about a TV show (say, The Mandalorian
) from TVmaze using one of its API listed here.
The show ID of The Mandalorian
is 38963
.
We pass the URL (embedding the show id) as a second argument inside the open()
function.
if(window.Promise) {
var promise = new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.tvmaze.com/shows/38963');
xhr.onload = function() {
if (xhr.status == 200) {
resolve(xhr.response);
} else {
reject(Error(xhr.statusText));
}
};
xhr.onerror = function() {
reject(Error('error fetching JSON data'));
};
xhr.send();
});
promise.then(function(data) {
console.log(JSON.parse(data));
}, function(error) {
console.log(error);
});
}
The value of the resolved Promise object is parsed using the JSON.parse()
method and printed into the console.
We can display the retrieved information in a page by populating some elements of the DOM. Add the below piece of HTML into the page.
<div style="width:350px;">
<img src="" style="width: 100%"/>
<span></span>
</div>
The image URL and the summary of the show from the retrieved data are assigned to the src
attribute of the <img/>
element and into the contents of the <span/>
element respectively.
promise.then(function(data) {
let d = JSON.parse(data);
document.querySelector("img").setAttribute("src", d.image.original);
document.querySelector("span").innerHTML = d.summary;
}, function(error) {
console.log(error);
});
Promise with fetch()
Method
fetch()
is a Promise-based method which retrieves information from the network asynchronously. This method is defined in the global Window
scope and need no attachment to any object for use.
A simple GET
request using fetch()
looks as follows:
fetch("https://api.tvmaze.com/shows/38963", {method: 'GET'})
.then(res => {
console.log(res);
});
For GET
request, passing the { method: 'GET' }
request object is optional. The below request works just fine.
fetch("https://api.tvmaze.com/shows/38963")
.then(res => {
console.log(res);
});
The promise returned is a Response
object, which is but just an HTTP response and not the actual JSON data we need.
To extract the JSON response on fulfilment of Promise, we need to chain the json()
method to the response as shown below. The resolved result will be available inside the subsequent then
statement.
fetch("https://api.tvmaze.com/shows/38963")
.then(res => res.json())
.then(res => console.log(res));
You can also use the text()
method in place of json()
, but you will need to parse it into a JavaScript object using the JSON.parse()
method.
fetch("https://api.tvmaze.com/shows/38963")
.then(res => res.text())
.then(res => console.log(JSON.parse(res)));