connect to an API
REST countries
[ fetch | then | catch | promise | json ]

Connect to API

Create an app that connects to the REST countries API and extracts data for a specified country.


APIApplication Programming Interface

An API (Application Programming Interface), is a set of rules and protocols that allows different software applications to communicate with each other. It defines the methods and data formats that applications can use to request and exchange information.

APIs structure their interactions through endpoints, which are designated URLs corresponding to accessible services or data.

When a client requires something, it submits a request to one of these endpoints.


URLUniform Resource Locator

A URL is a reference or address used to access resources on the internet. It specifies the location of a resource and the protocol used to retrieve it.

https://example.com/products/item1 URL

https protocol

example.com domain

/products/item1 path to the specific resource


Example ...

Find the capital of Spain.

Enter a country name ...

Spain country name

From the select input choose an option ...

Get information about country

capital of country selected option

The url containing the country name endpoint is sent to the server and the capital is extracted from the returned data.

["Madrid"] capital of country

Arrays are used to store multiple values in a single variable.

Each value is called an element, and each element has a numeric position in the array, known as its index.

Arrays are zero-indexed, meaning the first element is at index 0, the second at index 1, and so on.

Arrays can contain any data type, including numbers, strings, and objects.

const arr1 = [2, 4, 6]; array

arr1[0]; element at index 0 → 2

arr1[1]; element at index 1 → 4

arr1[2]; element at index 2 → 6

arr1[3]; element at index 3 → undefined index not found


Objects are a data structure used to store related data collections.

It stores data as key/value pairs, where each key is a unique identifier for the associated value.

Each key must be a string and must be unique, each value can be any data type.

If you define an object with duplicate keys, the last one will overwrite any preceding ones.

Find the value for any given key in the object.

const obj1 = {"A": 4, "B": 5, "C": 6 }; object

obj1["A"]; key "A" 4

obj1["B"]; key "B" 5

obj1["C"]; key "C" 6

obj1["D"]; key "D" undefined key not found

Find the value for any given key in the object.

const obj2 = {"A": 4, "B": 5, "C": 6 }; object

const str = "ABC"; string

obj2[str[0]]; 4

obj2[str[1]]; 5

obj2[str[2]]; 6

obj2[str[3]]; undefined key not found


Object.keys() static method returns an array with the keys of an object.

const obj3 = { "A": 4, "B": 5, "C": 6 }; object

const obj3Key = Object.keys(obj3);

console.log(obj3Key); returns ↴

["A", "B", "C"] array

obj3Key[0] "A"

obj3Key[1] "B"

obj3Key[2] "C"


Object.values() returns an array with the proprty values of an object.

const obj4 = { "A": 4, "B": 5, "C": 6 }; object

const obj4Val = Object.values(obj4);

console.log(obj4Val); returns ↴

[4, 5, 6] array

obj4Val[0] 4

obj4Val[1] 5

obj4Val[2] 6


Object.entries() static method returns an array of the key/value pairs of an object.

const obj5 = { "A": 4, "B": 5, "C": 6 }; object

const obj5Ent = Object.entries(obj5);

console.log(obj5Ent); returns ↴

[ ["A", 4], ["B", 5], ["C", 6] ] → array of arrays

obj5Ent[0] ["A", 4] array

obj5Ent[1] ["B", 5] array

obj5Ent[2] ["C", 6] array

obj5Ent = [["A", 4], ["B", 5], ["C", 6]] → array of arrays

obj5Ent[0][0] "A" access the first element of the first array

obj5Ent[0][1] 4 access the second element of the first array

obj5Ent[1][0] "B" access the first element of the second array

obj5Ent[1][1] 5 access the second element of the second array

obj5Ent[2][0] "C" access the first element of the third array

obj5Ent[2][1] 6 access the second element of the third array


Connect to an API using ↴

RESTful API → API based on REST design principles that follow a set of rules and conventions for building and interacting with web services.

Fetch API → provides an interface for making HTTP requests and processing the responses.

promise → object representing the eventual completion or failure of an asynchronous operation.

then → specify what should happen once that Promise is resolved.

catch → specify what should happen once that Promise is rejected.

json → lightweight, human-readable text format for data storage and transmission.

REST countries API → provides information about countries including their name, capital, population, currencies, flags, languages, timezones, and more.


REST APIRepresentational State Transfer

A REST API is any API that adheres to the principles of Representational State Transfer (REST). It is a set of guidelines for creating web services that allow for interaction with resources over HTTP.


RESTful API

A RESTful API is governed by several key constraints that ensure its effectiveness and scalability. These constraints include ...

Statelessness Each request from a client must contain all the information needed to process it. The server does not store any client context between requests, which simplifies server design and improves scalability.

Client-Server Architecture The separation of client and server allows for independent evolution of both. The client handles the user interface, while the server manages data storage and processing.

Cacheability Responses must define themselves as cacheable or non-cacheable, allowing clients to reuse responses for identical requests, thus improving performance.

Layered System A RESTful API can be composed of multiple layers, with each layer having its own responsibilities. This promotes scalability and security by allowing intermediaries like proxies and gateways.

Uniform Interface A consistent interface simplifies the architecture, allowing different clients to interact with the API in a standardized way. This includes using standard HTTP methods (GET, POST, PUT, DELETE) and resource representations (JSON, XML).

It allows different software applications to communicate over the internet using standard HTTP methods such as ...

GET request data from a server

POST send data to a server

PUT update existing data on a server

DELETE remove specified data from a server

While all RESTful APIs are REST APIs, not all REST APIs are necessarily RESTful. REST APIs have a higher level of adherence to REST principles.


Fetch API

The Fetch API provides an interface for making HTTP requests and processing the responses.

It provides an interface for fetching resources and is a more powerful and flexible replacement for XMLHttpRequest.

The fetch() method takes one mandatory argument, the path to the resource you want to fetch.

It returns a Promise that resolves to the Response object representing the response to the request. This happens once the request is completed, regardless of whether it was successful or resulted in an error.

The .then() method of Promise instances takes up to two arguments: callback functions for the fulfilled and rejected cases of the Promise.

It stores the callbacks within the promise it is called on and immediately returns another Promise object, allowing you to chain calls to other promise methods.

The catch() method of Promise instances schedules a function to be called when the promise is rejected. It immediately returns another Promise object, allowing you to chain calls to other promise methods.

The Fetch API uses request and response objects.

Request interface of the Fetch API represents a resource request.

Response interface of the Fetch API represents the response to a request.


Promises

A promise is an object representing the eventual completion or failure of an asynchronous operation.

It allows you to handle asynchronous operations more easily by providing a cleaner syntax compared to callbacks.

Promises have three states: pending, fulfilled, or rejected. When a promise is created, it is in a pending state.

It can then transition to either a fulfilled state if the operation is successful or a rejected state if it encounters an error.

Promises help in writing cleaner and more readable asynchronous code.

A Promise is in one of these states ...

pending → initial state, neither fulfilled nor rejected.

fulfilled → meaning that the operation was completed successfully.

rejected → meaning that the operation failed.

The eventual state of a pending promise can either be fulfilled with a value or rejected with a reason (error).

Promise pending

promise pending image

Promise fulfilled

promise fulfilled image

Promise rejected

promise rejected image

The .then() method is used to specify what should happen once that Promise is resolved, allowing you to handle the response data.

The method schedules callback functions for the eventual completion of a Promise - either fulfilled or rejected.

It stores the callbacks within the promise it is called on and immediately returns another Promise object, allowing you to chain calls to other promise methods.

The .catch() method of Promise instances schedules a function to be called when the promise is rejected. It immediately returns another Promise object, allowing you to chain calls to other promise methods.

promise.then((response) => {

// Handle the successful response

}).catch((error) => {

// Handle any errors

});


JSONJavaScript Object Notation

JSON is a text-based data format following JavaScript object syntax. It represents structured data as a string, which is useful when you want to transmit data across a network.

Even though it closely resembles JavaScript object literal syntax, it can be used independently from JavaScript. Many programming environments feature the ability to read (parse) and generate JSON.

In JavaScript, the methods for parsing and generating JSON are provided by the JSON object.

The json() method of the Response interface takes a Response stream and reads it to completion. It returns a promise which resolves with the result of parsing the body text as JSON.

Note that despite the method being named json(), the result is not JSON but is instead the result of taking JSON as input and parsing it to produce a JavaScript object.

JSON Parsing

The response from the server will be a JSON string, which we need to parse to convert it into a JavaScript object for further manipulation.

This can be accomplished using the JSON.parse() method.

const jsonStr = '{"name": "Spain", "capital": "Madrid"}'; → JSON string

console.log(jsonStr); returns ↴

{"name": "Spain", "capital": "Madrid"} → string

const obj6 = JSON.parse(jsonStr);

console.log(obj6); returns ↴

{name: "Spain", capital: "Madrid"} → JavaScript object


Syntax to connect to API

fetch(url, options)

.then(response => response.json())

.then(data => console.log(data))

.catch(error => console.error("Error:", error));

fetch make a request to the API

url API endpoint from which data is fetched

options (optional) specifies method, headers, body, etc

.then specify what should happen to the response

response.json() parses the response as JSON

.catch(error) handles any errors that occur during the request

If options are not used, this is a simple GET request, downloading the contents of the url.

A request is sent to the specified URL.

The server processes the request and sends a response.

The response is converted to JSON (or another format) using .json()

Errors are handled using .catch() or try-catch blocks.


Response object

The Response object of the Fetch API encapsulates the response received from the server and provides various properties and methods to access the data ...

body The body of the response, which can be read in various formats (e.g., text, JSON).

bodyUsed Stores a boolean value that declares whether the body has been used in a response yet

headers A Headers object containing the response headers

ok A boolean indicating whether the response was successful (status in the range 200-299)

redirected Indicates whether or not the response is the result of a redirect (that is, its URL list has more than one entry)

status The HTTP status code of the response (e.g., 200 for success, 404 for not found)

statusText A short description of the status code

type The type of the response (e.g., basic, cors)

url The URL of the response

jsonplaceholder API

https://jsonplaceholder.typicode.com/

jsonplaceholder is a simple fake REST API for testing and prototyping.

It has different endpoints that give us fake users, posts, todos, comments etc.

Syntax to connect to API

fetch("https://jsonplaceholder.typicode.com/")

.then(response => console.log(response))

.catch(error => console.error("Error:", error)); returns ↴

fetch response image

The request was successful.

ok true

status 200

Error handling

When making requests with fetch(), errors can occur due to network issues or invalid responses.

HTTP response status codes indicate whether a specific HTTP request has been successfully completed.

Responses are grouped in five classes:

100-199 informational response the request was received, continuing process

200-299 successful the request was successfully received, understood, and accepted

300-399 redirection further action needs to be taken in order to complete the request

400-499 client error the request cannot be fulfilled due to an issue that the client might be able to control

500-599 server error the server failed to fulfil an apparently valid request

ok read-only property of the response interface returns a Boolean.

If status in the range 200-299 true

If status not in the range 200-299 false

If response.ok is true then return the response data, else throw a new Error object with a custom error message.

if (response.ok) { request is successful

return response.json();

} else { error occurred

throw new Error("Network response was not ok");

}

Connect to API and return response data for users endpoint.

fetch("https://jsonplaceholder.typicode.com/users/")

.then(response => {

if (response.ok) {

return response.json();

} else {

throw new Error("Network response was not ok");

}

})

.then(data => console.log(data))

.catch(error => console.error("Error:", error)); returns ↴

fetch response image

fetch() initiates a network request to the provided URL.

response.ok checks if the HTTP response status is in the range of 200-299, indicating success.

return response.json() if the response is successful, the data is parsed as JSON for further use.

throw new Error() if the status code indicates an error (e.g, 404 or 500), an error is thrown to handle it.

catch(error) catches any errors (network or HTTP issues) and logs them to the console for debugging.

Error Examples ...

Console.error message - code throws new Error - Network response was not ok.

error image

Console.error message - Error: TypeError: Failed to fetch.

error image

Console.error message - resource not found (typo: user should be users)

response error image

Console.error message - (typo: comm should be com)

response error image

API key

An API key is a unique code that identifies calls made to an API. It is used to authenticate and/or authorize API users and to track their usage.

const API_KEY = "your-api-key-here";

const url = `https://api.example.com/data?key=${API_KEY}`;


REST countries API

The REST Countries API provides detailed information about countries around the world in a simple RESTful interface. Users can retrieve data such as country names, capital, population, languages, currencies, flags, and more.

Search by full name

The REST Countries API offers an endpoint specifically to search for countries by their full name. This endpoint is more precise than the Name endpoint, which returns all countries whose names partially match the query.

To use the Full Name endpoint, we need to specify the name of the country we want to look up in the API request URL and set the fullText query parameter to true.

The URL for this endpoint is ...

https://restcountries.com/v3.1/name/{name}?fullText=true

A URL is a reference or address used to access resources on the internet.

It specifies the location of a resource and the protocol used to retrieve it.

To search by country name - Spain

https://restcountries.com/v3.1/name/spain?fullText=true URL

https protocol

restcountries.com domain

/v3.1/name/spain?fullText=true path to the specific resource

The REST countries API is open source and free to use and does not require an API key.


Define the country name for which we want to fetch data.

const countryName = "Spain"; → user input

Select the data we want to retreive.

capital of the country → user input

capital will be the endpoint

capital endpoint image

Define a function getData to fetch data from an API.

function getData(countryName) {}

The function takes a string as input countryName and requests data from the REST countries API with that country name.

From the response, user selected data is retrieved.

If the requested endpoint is stored within an object, the specific data can to be accessed using ...

Object.values to return an array of the property values of the object.

Object.keys to return an array with the keys of the object.

Template literals denote strings using backticks ``

This lets you embed variables and expressions within your strings.

Construct the URL for the REST Countries API using template literals.

const url = `https://restcountries.com/v3.1/name/${countryName}?fullText=true` url

The fetch(url) function initiates a network request to the specified URL.

It returns a promise that resolves to the response of the request.

The Fetch API makes a GET request to the constructed URL.

fetch(url)

After error checking, the first .then() method processes the response by converting it to JSON format.

.then((response) => {}

Check if the response is OK (status in the range 200-299)

if (!response.ok) {}

If not, throw an error with the status code.

throw new Error(`HTTP error! status: ${response.status}`)

If response is ok, parse the JSON from the response.

return response.json()

The second .then() method accesses the first element of the returned data array and extracts the data (capital).

.then((data) => {

Extract the data from the response data

const res = data[0].capital res

Log result to the console.

console.log(res)

If the country name is invalid or the request fails, the .catch() method captures the error and logs a message.

.catch((error) => {

console.error("Fetch error:", error.message);

console.log("Please enter a valid country name")

})


Call the function with ↴

getData (countryName);


Connect to REST countries API and return the capital of Spain.

const countryName = "Spain";

function getData (country) {

const url = `https://restcountries.com/v3.1/name/${countryName}?fullText=true`;

fetch(url)

.then((response) => {

if (!response.ok) {

throw new Error(`HTTP error! status: ${response.status}`);

}

return response.json();

})

.then((data) => {

const res = data[0].capital;

console.log(res);

})

.catch((error) => {

console.error("Fetch error:", error.message);

console.log("Please enter a valid country name");

});

}

call function

getData(countryName); returns ↴

["Madrid"]

Connect to REST countries API