Lecture 14

Using fetch with APIs

Agenda

Brief review of Promises/AJAX

Using fetch with public APIs

CP3 out now, Midterm Monday

Select questions from Wednesday:

  1. could you please go over anonymous functions
  2. Lab hours:
    • Is there an IPL for this class?
    • Could there be more WPL hours?
  3. [...] where one can find past midterms, if anywhere?
  4. What is the point using API? And where and when I need to use it?

JSON and AJAX

  • JSON introduced as object type to package/process structured data
  • AJAX introduced with Promises and fetch to fetch data from a server
  • Used the fetch(URL).then(...).then(...).catch(...) pipeline to handle requests

AJAX fetch template

When we make a call to fetch data (whether it's HTML, txt, JSON, etc) we use a function in JavaScript called fetch, which takes a URL path to fetch data from.

Here's the general template you will use for most AJAX code:

const BASE_URL = ""; // you may have more than one

// Step 1. Write a function to "fetch" data from a URL
function makeRequest() {
  let url = BASE_URL + "?query0=value0"; // some requests require parameters
  fetch(url)
    .then(checkStatus)
    //.then(resp => resp.text()) // use this if your data comes in text
    //.then(resp => resp.json()) // or this if your data comes in JSON
    .then(processData)
    .catch(handleError); // define a user-friendly error-message function
}

// Step 2: Implement a function to process the response data. You may want to break this apart
// into multiple functions.
function processData(responseData) {
  // Do something with your responseData! (build DOM, display messages, etc.)
}

// Step 3. Include the checkStatus function
function checkStatus(response) {
  if (!response.ok) { // response.status >= 200 && response.status < 300
     throw Error("Error in request: " + response.statusText);
  }
  return response;
}

JS

Promises and Fetch

We initiate a fetch of a URL

A fetch returns a Promise

Promises are good because...

  • They help deal with code that has an uncertain outcome
  • They separate the completion of the fetch request from the page logic
    • Lets us reuse the same logic and handle completion in different ways (AJAX logic vs page insertion, for example)
  • Chaining of Promises gives us a nice data flow, like down a pipe!

States of a Promise

Three states of a Promise: pending, resolved, rejected

Using Promises with fetch

We won't be constructing Promises, but will be using them when we fetch information from a server, which is an uncertain task

The returned Promise contains a value that is a Response from the requested resource, which we can get then. after the fetch call.

fetch(url).then((resp) => {
    // resp is a Response object!
});

JS

What's in a Response?

The Response object

Property Description
response.status Status code (e.g. 200, 400, etc.)
response.ok Whether the response has a success (2XX) status code, short for:
response.status > 200 && response.status <= 300)
response.statusText Status text returned in the response (e.g. "200 OK", "400 Bad Request", "503 Service Unavailable")
response.json(), response.text() Methods to extract the response body depending on the data format

We will use the Response returned (in a Promise) from fetch to:

  1. Check response.ok
  2. If not, throw an Error which will jump immediately to a catch statement. It's good to construct the Error with details about the response.statusText
  3. Otherwise, extract the data we want with response.text() or response.json()

Recall Status Codes

Set by the server

A 2XX status code (e.g. 200, 201, etc.) will indicate a successful request

Other status codes indicate a failure in the request

  • 3XX: Redirects
  • 4XX: Client errors (400: Bad Request, 403: Forbidden, etc.)
  • 5XX: Server errors

Full list here

We can access the status code and status text with the Response object

This is a useful service to test different error codes: https://httpstat.us/

Demo: status-tester.html

Why AJAX?

Recall our earlier Cafe Demo

Version 1 (HTML): Menu in HTML

Version 2 (JS): Menu in JSON as local variable in JS

Version 3: Let's use fetch with the JSON on a server!

Application Program Interfaces (APIs)

An application programming interface (API) is a communication protocols that allows two pieces of software to communicate.

A Web API is a set of pre-defined URLs with parameters that allow a user to get information from a web server. Can be used by many types of clients.

API diagram

Source: https://happycoding.io/tutorials/java-server/rest-api

The Client-Server Model

XKCD server attention span.

Source: https://xkcd.com/869

The Client-Server Model

Client-Server

Source: https://en.wikipedia.org/wiki/Client%E2%80%93server_model

The Request/Response Transaction with Web APIs

REST API diagram

Much like the request/response analogy at a restaurant!

Examples of APIs

Fetching data from a web service

To make a request to a web service (API), we need to know:

  1. Who to ask (the url)
  2. Do we have permission to ask (any API keys/tokens)
    • Not for elephants, but NASA/TMDB require them; add as additional query parameter
  3. What to ask (any query parameters)
  4. What format we get answers in (the response data format, preferably text or JSON)

Check your Understanding

Consider the following request we might make with fetch:

function makeRequest() {
  let requestString = "https://api.nasa.gov/planetary/apod?" +
                      "api_key=DEMO_KEY&date=2018-09-30";
  fetch(requestString)
    .then(checkStatus)           // 1
    .then((resp) => resp.json()) // 2
    .then(processData)           // 3
    .catch(handleError);         // 4
}

JS

  1. Who are we asking for data from (the base url)?
  2. What query parameters are we using? What are the values of the parameters?
  3. What is the purpose of each step (1 through 4)?

Note: Convenient In-browser JSON Formatter

We're about to dive into how to get started with a public API. The first thing you usually want to do is to find a url with query parameters you're interested in, and see if you can view it on your browser.

There is a great Chrome extension to format nested JSON returned by different API's!

Chrome Extension: JSON View

Example API Requests

The following slides provide a few examples of breaking down request URLS for various APIs, starting with the NASA APOD API.

API 1: NASA APOD (Astronomy Photo of the Day) API

Solution: apod.html

  1. What kind of format is the response data? JSON
  2. Do you need an API key? Yes* *(but you can make 50 calls per day with "DEMO_KEY" as your api key parameter!
  3. What is the base url? https://api.nasa.gov/planetary/apod

API 1: NASA APOD (Astronomy Photo of the Day) API

Examples:

API 2: Datamuse API

Note: Go "down" slides for more

An word-querying API: https://www.datamuse.com/api/

  1. What kind of format is the response data? JSON
  2. Do you need an API key? No
  3. What is the base url? https://www.api.datamuse.com

API 2: Datamuse API

Examples:

API 3: XKCD

Note: Go "down" slides for more

"Documentation": https://xkcd.com/json.html

  1. What kind of format is the response data? JSON
  2. Do you need an API key? No
  3. What is the base url? https://xkcd.com/

Examples:

Comic of the Day: https://xkcd.com/info.0.json

A note on "CORS"

Many sites and APIs you try to use will give you an error about CORS.

For example, we used the Elephants API earlier just by opening the API endpoint in the browser.

Try doing a fetch with it!

CORS: Cross-Origin Resource Sharing

CORS on MDN

Security measure browsers have implemented that restricts one site from accessing resources in another unless explicitly given permission.

Most of the APIs we've chosen for CP3 or demo'd today have explicitly allowed *, meaning anyone.

Many APIs you run into around the internet will be more locked down than this.