Fetch
2022-03-29T15:30:00-05:00
Agenda
- Revisit button click
- Add a result field
- Add an image
- Make an API call with
fetch()
- Use the response from
fetch()
to manipulate elements.
Slides
https://comp426-2022-spring.github.io/slides/w11-00.html
Useful links
HTML DOM Element setAttribute() - w3schools
Use Express to deliver HTML files - Chris Sev
Promises - MDN
HTML DOM Button Object
HTML DOM Form Object
fetch
Introduction to fetch() - Matt Gaunt
How to Use the JavaScript Fetch API to Perform HTTP Requests - Ryan Glover
fetch() - MDN
Using the Fetch API - MDN
How to use Fetch with async/await - Dmitri Pavlutin
Notes
Below is the coin flip interface that we put together in class.
You can serve this page using browser-sync -sw
, if you have placed it in a node package with browsersync installed in it.
It will serve on port 3000.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
<html>
<head>
<title>Demo Coin</title>
<style>
img#quarter {
width: 100px;
}
</style>
</head>
<body>
<!-- A "coin" button -->
<button id="coin">Flip?</button>
<!-- A status paragraph -->
<p id="active"></p>
<!-- A result paragraph-->
<p>Result: <span id="result"></span></p>
<!-- An image of a US quarter (North Carolina variant) -->
<img src="coin.jpg" id="quarter">
<script>
// Event listener for whatever is being clicked
// document.addEventListener("click", activeNow);
// Replace text in anything with "active" id
// function activeNow() {
// const active_now = document.activeElement
// document.getElementById("active").innerHTML = active_now;
// console.log(active_now)
// }
// Button coin flip element
const coin = document.getElementById("coin")
// Add event listener for coin button
coin.addEventListener("click", flipCoin)
function flipCoin() {
fetch('http://localhost:5000/app/flip/', {mode: 'cors'})
.then(function(response) {
return response.json();
})
.then(function(result) {
console.log(result);
document.getElementById("result").innerHTML = result.flip;
document.getElementById("quarter").setAttribute("src", result.flip+".jpg");
coin.disabled = true
})
// let flip = "FLIPPED"
// document.getElementById("coin").innerHTML = flip;
// console.log("Coin has been flipped. Result: "+ flip)
}
</script>
</body>
</html>
|
You will need to enable Cross-Origin Resource Sharing (CORS) server-side since your server will be listening on a different port (5000).
To do this, run npm install cors
in your server package repository.
Then add the following to your server.js
:
1
2
3
4
|
// Add cors dependency
const cors = require('cors')
// Set up cors middleware on all endpoints
app.use(cors())
|
Here are the coin images that I used:
2022-03-31T15:30:00-05:00
Agenda
- Using async and await with fetch
- Use fetch to POST data to API
- Serve static html from Express
Useful links
How to use Fetch with async/await - Dmitri Pavlutin
How to use fetch to POST form data as JSON to your API - Simon Plenderleith
Serving static files with Node and Express.js - Janith Kasun
Notes
Here is the working example for a simple form that sends a POST request to an API endpoint defined at http://localhost:5000/app/flip/coins/.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
<html>
<head>
<title>Demo Coin</title>
</head>
<body>
<div id="multi">
<h1>Flip many coins</h1>
<form id="coins">
<label for="number">
<strong>How many coins?</strong>
</label>
<input type="number" name="number" id="number">
<input type="submit" value="Flip 'em!">
</form>
<h2>Results</h2>
<p id="heads"></p>
<p id="tails"></p>
</div>
<script>
// Our flip many coins form
const coins = document.getElementById("coins")
// Add event listener for coins form
coins.addEventListener("submit", flipCoins)
// Create the submit handler
async function flipCoins(event) {
event.preventDefault();
const endpoint = "app/flip/coins/"
const url = document.baseURI+endpoint
const formEvent = event.currentTarget
try {
const formData = new FormData(formEvent);
const flips = await sendFlips({ url, formData });
console.log(flips);
document.getElementById("heads").innerHTML = "Heads: "+flips.summary.heads;
document.getElementById("tails").innerHTML = "Tails: "+flips.summary.tails;
} catch (error) {
console.log(error);
}
}
// Create a data sender
async function sendFlips({ url, formData }) {
const plainFormData = Object.fromEntries(formData.entries());
const formDataJson = JSON.stringify(plainFormData);
console.log(formDataJson);
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: formDataJson
};
const response = await fetch(url, options);
return response.json()
}
</script>
</body>
</html>
|
To make this work, you will need to have the following body parser middleware (built into Express) enabled in your server.js
script:
1
2
|
// Allow JSON body messages on all endpoints
app.use(express.json())
|
In addition, you will need this endpoint defined, which differs slightly from the versions that you might have developed for previous assignments:
1
2
3
4
5
6
|
// Flip a bunch of coins with one body variable (number)
app.post('/app/flip/coins/', (req, res, next) => {
const flips = coinFlips(req.body.number)
const count = countFlips(flips)
res.status(200).json({"raw":flips,"summary":count})
})
|
And finally, if you place index.html
into a subdirectory named www
, you can add this line to your server script and it will serve the interface along with the API when you run node server.js
:
1
2
|
// Serve static HTML files
app.use(express.static('./www'))
|