Fetch and AJAX
AJAX (Asynchronous JavaScript and XML)
XML HTTP Request (XHR)
GET Request
var request = new XMLHttpRequest();
request.open('GET', '/words', false);
request.send('word='+word+'&type='+wordType);
if (request.status == 200) {
console.log(request.responseText);
}
POST Request
request.open('POST', '/search.php', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.setRequestHeader('Cache-Control', 'no-cache');
request.onreadystatechange = function () {
console.log(request.status, request.responseText);
};
request.send("jsonData=" + JSON.stringify(wordData));
XML HTTP Request
window.XMLHttpRequest
var request = new XMLHttpRequest();
Methods
open(method, url, [isAsyncronous])
setRequestHeader(header, value)
send(body)
Properties
readyState
(4
= ready)status
(200
= OK)statusText
response
responseText
Events
readystatechange
abort
load
loadstart
loadend
Load DocumentFragment via XHR
const view = new DocumentFragment();
const xhr = new XMLHttpRequest();
xhr.onload = event => {
const newDocument = event.target.response;
const newView = newDocument.querySelector('.desired-view');
// Copy in the child nodes from the parent.
while (newView.firstChild) {
view.appendChild(newView.firstChild);
}
// Add the fragment to the page.
this.appendChild(view);
};
xhr.responseType = 'document';
xhr.open('GET', `about.html`);
xhr.send();
Fetch API
fetch("animals.json")
.then((response) => response.json())
.then((data) => (animals = data));
await (await fetch('https://api.github.com/users/markusdoppler')).json()
await fetch('https://api.github.com/users/markusdoppler').then(data => data.json())
fetch('https://api.github.com/users/markusdoppler').then(data => data.json()).then(json => console.log(json))
fetch(fileOrURL)
.then((data) => {
// ...
})
.catch(error => {
// ...
});
const request = new Request('data.json');
fetch(request).then(function(response) {
return response.text();
}).then(function(text) {
console.log(text);
});
Optional Parameter
fetch(url, {
method: 'GET',
})
fetch(url, {
method: "POST",
body: new URLSearchParams({ view: "home", id: currentItem.id, item: currentItem.title })
})
fetch(url, { mode: "no-cors" })
fetch(url, {
headers: { 'mode': 'cors' }
})
fetch(url, {
mode: 'no-cors',
header: {
'Access-Control-Allow-Origin': '*'
}
})
Axios library
const axios = require('axios');
await axios.get('/user', { params: 12345 });
await axios.post('/user', { params: 12345 });
axios.post('/user', { params: 12345 })
.then(() => {
// ...
}).catch(() => {
// ...
});
JSON
(JavaScript Object Notation)
Stringify object
JSON.stringify({ name: 'Tim', age: 17 })
Parsing JSON
text = "{ name: 'Otto', age: 17 }"
JSON.parse(text)
const jsonData = `{ "number": 5, "colour": "red" }`;
const data = JSON.parse(jsonData, function(key, value) {
if (!isNaN(parseInt(value))) {
return parseInt(value);
} else {
return value;
}
});
Promises Overview
promise
.then( /* ... */ )
.then( /* ... */ )
.then( /* ... */ )
.catch( /* ... */ )
Create
const ride = new Promise((resolve, reject) => {
if (arrived) {
resolve("driver arrived")
} else {
reject("driver bailed")
}
})
Consume
ride
.then(value => {
console.log(value)
// driver arrived
})
.catch(error => {
console.log(error)
// driver bailed
})
.finally(() => {
console.log("all settled!")
})
Promises
Promise object
new Promise((resolve, reject) => { /* ... */ });
resolve(data)
:reject(error)
:
Promise.all([promise1, promise2])
Await Promise
await promise
Chained Promises
promise.then()
promise.catch()
promise.finally()
promise.any()
promise.allSettled()
Promise example via setTimeout()
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
if (everythingIsFine) resolve('✅')
else reject('❌');
})
})
const answer = await promise
one-line Promise
await new Promise((resolve, reject) => { setTimeout(() => { if (everythingIsFine) resolve('✅'); else reject('❌'); }); });
.then()
and .catch()
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Fetched user");
resolve({ user: "Alfred" });
reject(new Error('No users found'));
})
});
promise.then(user => {
console.log(user);
}).catch(err => {
console.log(err.message);
});
Function that returns a Promise
function getData(username) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({"username": "winfy153", "points": 127});
})
});
}
getData('winfy153')
.then(user => console.log(user))
.catch(err => console.log(err));
"Parallel" Promises
const promise1 = new Promise(resolve => {
setTimeout(() => {
console.log("got data");
resolve( {title: "The Why Café"} );
}, 2000)
})
const promise2 = new Promise(resolve => {
setTimeout(() => {
console.log("got data 2");
resolve( {title: "The Why Are You Here Café"} );
}, 3000)
})
Promise.all([promise1, promise2])
.then(result => console.log(result))
const [weather, store] = Promise.all(getWeather(), getStores());
Async + Await
Let synchronous code look like synchronous code
async function displayUser(email, password) {
try {
const user = await getUser('email@me.com', "12345")
console.log(user.email);
} catch (error) {
console.log("Cannot get user: ", error);
}
}
displayUser('email@me.com', "12345");
Image Loading Example
async function load() {
const image_status = await load_image(image_src).then(msg => { return msg }).catch(err => { return err });
console.log("image load", image_status)
// add image to DOM
}
async function load_image(src) {
return await new Promise((resolve, reject) => {
let img = new Image();
img.onload = () => resolve('✅');
img.onerror = () => reject('❌');
img.src = src;
})
}
Promise vs. async-await
Promise
document.addEventListener("click", () => {
import("./module.js").then(({ default: printModule }) => {
printModule()
})
})
Async Await
document.addEventListener("click", async () => {
const { default: printModule } = await import("./module.js")
printModule()
})
Async and Await
Let asynchronous code look like synchronous code!
async function getData() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('done'), 3000)
})
let result = await promise
console.log(result)
}
getData()
A little history: How was it done before
Callback
function manageTheWeather() {
getTheWeather(..., showGraphsCallback(weather))
}
Promises
function manageTheWeather() {
getTheWeather().then(weather => showGraphs).catch(err => handleErrors)
}
Async/await
async function manageTheWeather() {
var weather = await getTheWeather()
showGraphs(weather)
}
HTTP Header
Content-Type: text/html
Content-Type: text/html; charset=UTF-8
Content-Type: text/plain
Content-Type: application/json
Same-Origin Policy (SORS – Same-Origin Resource Sharing)
Allowed if the following are equal:
- protocol (HTTP or HTTPS)
- domain
- port
CORS (Cross-Origin Resource Sharing)
Origin is not just the hostname, but a combination of port, hostname and scheme, such as http://mysite.example.com:8080/
Server-side HTTP header Just remember: the origin responsible for serving resources will need to set this header.
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Origin: *
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);