1 of 28

Client-Side Templating & Fetch

CS 396: �Introduction to Web Development

Spring, 2021

2 of 28

Announcements

  1. HW3: Deadline extended to Friday
  2. HW4: To be released on Friday, due the following Tuesday
    • No LCs if you got it in by Friday (remind the graders)

3 of 28

Outline

  1. Review
  2. Client-side templates
  3. Intro to AJAX & Fetch
  4. Error handling
  5. Headers & CORs
  6. Practice

4 of 28

Outline

  • Review
  • Client-side templates
  • Intro to AJAX & Fetch
  • Error handling
  • Headers & CORs
  • Practice

5 of 28

Recall: Server-Side Templates

In HW2, the Photo App interface was generated on the server. Specifically:

  1. Python fetched the data from “faker” (but could have been from a database too)
  2. Python “merged” this data with a template (using Jinja) to create a fully-generated HTML file
  3. Python then sent this HTML file down to the client:
    1. Demo: https://photo-app-demo.herokuapp.com/

6 of 28

Next Two Weeks: Client-Side Templating

In HW4, we will practice building client-side templates. Specifically:

  • Server sends down the skeleton of an HTML page with some embedded JavaScript
  • Then, the Browser reads the instructions from the JavaScript files and dynamically builds the page on-the-fly by manipulating the DOM
  • Typically, either:
    • JSON is embedded in the page as a variable, or
    • Data is fetched after the pages loads via a REST API endpoint.

�Example: https://www.instagram.com/

7 of 28

Outline

  • Review
  • Client-side templates
  • Intro to AJAX & Fetch
  • Error handling
  • Headers & CORs
  • Practice

8 of 28

Data → HTML

const player = {

name: "Jane",

pic: "http://website.com/avatar.png",

score: 300

};

<div class="card">

<img src="http://website.com/avatar.png">

<p>Jane scored 300 points</p>

</div>

The Data

The HTML�(Goal)

9 of 28

You COULD do one big string concatenation...

...but string concatenation is annoying – difficult to read and easy to make mistakes.

const html = '<div class="card">' +

'<img src="' + player.pic + '">' +

'<p>' + player.name + ' scored ' +

player.score + ' points</p>' +

'</div>';

9

10 of 28

ES6 Introduced a better way: Client-side templates

  • Templates, or “template literals” are strings that allow you to embedded expressions
  • They’re convenient for generating larger chunks of HTML from lists of objects
  • Uses the “backtick” character (instead of regular single or double quotes) to indicate that you are specifying a template (above the tab key):

` <template goes here> `

  • Within the template, expressions represented like this:

${ my_expression }

10

11 of 28

Rewriting previous HTML using template syntax

const html = `

<div class="card">

<img src="${player.pic}">

<p>

${player.name}'s high score is:

${player.score}

</p>

</div>`;

12 of 28

More on templates

const name = 'Walter';

console.log( ` A template

can be multiple lines.

It can also evaluate expressions like:

${2 + 2} or� ${name} or

${getTodaysDate()}

` );

12

13 of 28

Demos

  • 01-create-cards-from-list-of-objects
  • 02-photo-gallery
  • 03-challenge-activity

13

14 of 28

Outline

  • Review
  • Client-side templates
  • Intro to AJAX & Fetch
  • Error handling
  • Headers & CORs
  • Practice

15 of 28

1. Intro to AJAX

AJAX

  • AJAX: Stands for Asynchronous JavaScript and XML
  • Enables JavaScript to make server requests and (optionally) update the current screen
  • Not easy to tell that information is even being transmitted to/from a server
  • Came on the scene ~2004 (made popular w/Google Mail and Google Maps)

15

16 of 28

1. Intro to Fetch

JavaScript’s Fetch API

  • The Fetch API is a newer instantiation of asynchronous server-client web communication
  • Provides an interface for fetching resources (including across the network). The new API provides a more powerful and flexible feature set (improving upon AJAX)

16

17 of 28

1. How Fetch Works

fetch('https://photo-app-demo.herokuapp.com/api/posts')

.then(response => response.json()) // callback function

.then(data => console.log(data)); // callback function

  • The simplest use of fetch() takes one argument — the path to the resource you want to fetch — and returns a promise containing the response (a Response object)
  • This is just an HTTP response, not the actual content. To extract the body content from the response, we use one of the content methods – in this case the json() method – which also returns a promise.

18 of 28

2. What is a Promise?

  • Promises exist to handle asynchronous functionality
  • If you request a resource the cloud (i.e., someone else’s computer that lives somewhere else), you don’t know how long it’s going to take to process the request.
    • Slow machine?
    • Network traffic?
    • Patchy WIFI!
  • To handle this, a “promise” allows you to execute a piece of functionality only after the request completes.

19 of 28

2. Promises: Two Syntaxes > “then” method

Using the promise’s “then” method, which will execute a callback function when the promise finishes its business...�

let url = 'https://photo-app-demo.herokuapp.com/api/posts'

fetch(url)

.then(response => response.json()) // callback function

.then(data => console.log(data)); // callback function

20 of 28

2. Promises: Two Syntaxes > async await

Using the async / await technique. Instead of using “then()” the await keyword ensures that the next line doesn’t execute until the promise resolves.

const getPosts = async () => {

let url = 'https://photo-app-demo.herokuapp.com/api/posts';

const response = await fetch(url);

console.log(response);

const jsonData = await response.json();

console.log(jsonData);

};

getPosts();

21 of 28

Outline

  • Review
  • Client-side templates
  • Intro to AJAX & Fetch
  • Error handling
  • Headers & CORs
  • Practice

22 of 28

Error Handling

  • If the response has an error code (e.g. HTTP 404, 400, or 500), the except won’t get triggered.
  • It will resolve normally, but the ok property of the response set to false if the response isn’t in the range 200–299)
  • It will only reject on network failure or if anything prevented the request from completing.

23 of 28

Example: No Error Handling

fetch('/https://photo-app-demo.herokuapp.com/api/posts')

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

.then(data => {

console.log('Success:', data);

});

24 of 28

Example: With Error Handling

fetch('/https://photo-app-demo.herokuapp.com/api/posts')

.then(response => {

if (!response.ok) {

// send to catch block:

throw Error(response.statusText);

} else {

return response.json();

}

})

.then(data => {

console.log('Success:', data);

})

.catch(err => {

console.error('Error:', err);

});

25 of 28

Example: With Error Handling

const getPosts = async () => {

try {

let url = 'https://photo-app-demo.herokuapp.com/api/posts';

const response = await fetch(url);

console.log(response);

const jsonData = await response.json();

console.log(jsonData);

} catch(err) {

console.error(err);

}

};

getPosts();

26 of 28

Outline

  • Review
  • Client-side templates
  • Intro to AJAX & Fetch
  • Error handling
  • Headers & CORs
  • Practice

27 of 28

Cross-Origin Resource Sharing (CORS)

  • Some kinds of requests have an extra security check called a “preflighted request” (see this MDN article). In these requests, the browser and server communicate to determine whether the request is safe to send based on particular criteria set by each.
  • For certain AJAX requests, the server has to explicitly allow cross-origin resource sharing by setting the Access-Control-Allow-Origin response header.
  • If you want to allow clients all over the Internet to access your REST API through a browser, you’ll need to set some security headers

28 of 28

Practice Time

04-fetch-get

05-fetch-search