On the top half of the notecard write what you feel like you "got" so from doing CP 1 and CP 2 and Homework 1.
On the bottom of the notecard, write something you feel you still need to understand, or that would help you understand this material, particularly for HW 2.
On the back of the notecard, write any questions or topics that you would particularly like to see reviewed during lab, exploration session, or optional lecture on Friday.
HW 2 Notes
Code Step By Step problems up: Baby Sloth, Domino, Street, Resume
Answer to Friday's problem
Real world motivation for this topic!
Arrow functions
Intro to AJAX, fetch and promises
Given the JSON data at right, what expressions would produce.
Assume the JSON data is stored in a object called data
.
For instance, the window's title is data.window.title
{
"window": {
"title": "Sample Widget",
"width": 500,
"height": 500
},
"image": {
"src": "images/logo.png",
"coords": [250, 150, 350, 400],
"alignment": "center"
},
"messages": [
{"text": "Save", "offset": [10, 20]},
{"text": "Help", "offset": [ 0, 50]},
{"text": "Quit", "offset": [30, 15]}
],
"debug": "true"
}
Example: the window's title is :
let title = data.window.title; // title === "Sample Widget"
What the debug flag is set to?
let debug = data.debug; // debug === "true"
The image's third coordinate?
let coord = data.image.coords[2]; // coord === 350
The number of messages?
let len = data.messages.length; // len === 3
The y-offset of the last message?
let y = data.messages[len - 1].offset[1]; // y === 15
All of the class' teams group names (with student names) were typed into a .json
file which we will use in an example shortly.
The structure of the file is:
{
"teams": [
{
"name": "Catz",
"students": ["Jack", "Spot", "Whitney", "Charlie"]
},
{
"name": "Dawgs",
"students": ["Mowgli", "Ruby", "Moss"]
}
]
}
What could would you write to tell how many students groups there are and how many students are actually in a group?
let data = {
"teams": [
{
"name": "Catz",
"students": ["Jack", "Spot", "Whitney", "Charlie"]
},
...
}
let numTeams = data.teams.length; // numTeams === 39
let count = 0;
for (let i=0; i< data.teams.length; i++) {
count += data.teams[i].students.length;
}
How many people do you think actually signed up for a group? 108
(View Page Source on that page or see below for an example of the code...)
<select id="homework">
<option value="">(choose an assignment)</option>
<optgroup label="Hello Buggy">
<option value="../homework/HelloBuggy-expected-output.txt">Hello Buggy Expected Output</option>
</optgroup>
<optgroup label="Star Car (random seed = 28)">
<option value="../homework/StarCar_expected_output_1.txt">Star Car Expected Output (default)</option>
<option value="../homework/StarCar_expected_output_2.txt">Star Car Expected Output (lower case test)</option>
</optgroup>
...
</select>
=>
Fat arrow functions are just another way of writing an anonymous function.
//define an anonymous function and assign it to mult
let mult = function(a, b) { return a * b };
let result = mult(4, 5); // result === 20
// create an anonymous function mult2 using the fat arrow notation
let mult2 = (a, b) => a * b;
let result2 = mult2(4, 5); // result2 === 20
You do not need to use fat arrow functions in your work but ...
this
Some sample basic syntax (from MDN)
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// equivalent to: => { return expression; }
// Parentheses are optional when there's only one parameter name:
(singleParam) => { statements }
singleParam => { statements }
// The parameter list for a function with no parameters should be written with a pair of parentheses.
() => { statements }
let max = (a, b) => a > b ? a : b;
// Array filtering
let arr = [1, 2, -1, 0, 3, 4, 6, 20];
let even = arr.filter(v => v % 2 == 0);
// [2, 0, 4, 6, 20]
function() { }
) or use fat arrow functions as you feel
comfortable with them. You do NOT have to use fat arrow functions at all.
All of the pages that we've made up until now have content, style, and behavior.
Web applications are webpages that pull in additional data and information as the user progresses through them, making it feel similar to a desktop application.
Some motivations for making web pages into web applications:
Your code waits for the request to completely finish before proceeding. Might be easier for you to program, but the user's entire browser LOCKS UP until the download is completed, which is a terrible user experience (especially if the page is very large or slow to transfer)
Use the inspector, watch the network tab to see the requests that go out.
Using Javascript to pull in more content from the server without navigating the page to a new url
Although we are showing you this, it is for context only, we will not be using the "XML over HTTP" method of AJAX calls.
let xhr = new XMLHttpRequest();
xhr.open(method, url, [async/sync]);
xhr.onload = function() { /* handle success */ };
xhr.onerror = function() { /* handle failure */ };
xhr.send();
let xhr = new XMLHttpRequest();
xhr.open("GET", "data.txt");
xhr.onload = function() { alert(this.responseText); };
xhr.onerror = function() { alert("ERROR!"); };
xhr.send();
The XMLHttpRequest
object can be used synchronously or asynchronously.
So this functionality could be called S/Ajax or A/Sjax. But Ajax has a nice ring to it.
It's better to use async so that the page doesn't block waiting for the page to come back. We have no use cases in this class for using Ajax synchronously.
the XMLHttpRequest
object can be used to fetch anything that you can fetch with your browser.
This includes XML (like in the name), but also JSON, HTML, plain text, media files.
So it could be called Ajaj or Ajah or Ajat. But Ajax has a nice ring to it.
The Fetch API was created in 2014 and incorporated into the window
DOM object.
(function(){
...
function doWebRequest() {
let url = ..... // put url string here
fetch(url);
}
You can use a relative path name to fetch
a file file that is
retreived from the same directory as the .js
file.
You can also pass absolute path to a file (i.e. a full URL) in the argument to
fetch
function loadTeams() {
const url = "teams.txt";
fetch(url);
...
}
Now that we've done a fetch
, we need to do something with the data that
comes back from the server.
But we don't know how long that will take or if it even will come back correctly!
The fetch
call returns a Promise
object which will help
us with this uncertainty.
Promises have three states:
Example: “I promise to post CP 3”
Pending: Not yet posted
Fulfilled: CP 3 posted
Rejected: Wrong homework posted, or not posted in time
Promise
sPromises have three states:
let promise = new Promise(function(resolve, reject) {
// do something uncertain (like make an ajax call)
if (success) {
resolve(); // Fulfilled
} else {
reject(); // Rejected
}
});
Promise
is returned from a fetch
call
We will be using promises when we fetch
information from a
server, which is an uncertain task
We give you "boilerplate" starting code because you will use this frequently
fetch
Code Skeleton
// based on: https://developers.google.com/web/updates/2015/03/introduction-to-fetch
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response.text();
} else {
return response.text().then(Promise.reject.bind(Promise));
}
}
function callAjax() {
let url = ..... // put url string here
fetch(url)
.then(checkStatus)
.then(function(responseText) {
//success: do something with the responseText
})
.catch(function(error) {
//error: do something with error
});
}
fetch
Code Skeleton (better variation)
function checkStatus(response) { // boiler plate code given out
...
}
function callAjax() {
let url = ..... // put url string here
fetch(url)
.then(checkStatus)
.then(handleResponse)
.catch(handleError);
}
function handleResponse(responseText){
//success: do something with the responseText
}
function handleError(error){
//error: do something with error
}
A real world example for randomizing groups of people!
(Click on the image and View Page Source on that page to see the code...)
Generally speaking, you can only send Ajax requests to the server that your page came from.
This is to prevent rogue JavaScript from being able to call out to any server and pull in whatever content it wants to.
Mostly, you can't do Ajax request when your URL starts with file:///
(i.e. you've
double clicked on your .html
file to bring it into the browser.
A few possiblities here
The help deal with uncertainty in your code. You never know exactly what will happen when you make an Ajax call, so wrapping the call in a Promise is a nice way to deal with the uncertainty.
The paradigm is nice because you write the anonymous function that defines the promise, so you are the one who writes the code that determines whether the promise was 'fulfilled' or 'rejected'.
You also define what happens after the Promise fulfills with the then
function, and what happens
when it rejects in the catch
function.