JavaScript: Promise w/ setTimeout(), XMLHttpRequest and fetch()

A JavaScript Promise object allows us to perform asynchronous tasks, representing its eventual value.

js-promise The above promise icon is by Freepik from https://www.flaticon.com

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.

tvmaze api

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.

js promise fetch response json

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);
					  	});
					
				
js promise fetch response display

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.

js promise fetch response

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));
					
				
js promise fetch response json

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)));