Comunicació amb el servidor
Índex
AJAX
El motor de Javascript
Dins del navegador s’encarrega de:
Execution Context i Call Stack
const second = () => {
console.log('Hello there!');
}
const first = () => {
console.log('Hi there!');
second();
console.log('The End');
}
first();
Analitzar Call Stack
Web APIs
const networkRequest = () => {
setTimeout(() => {
console.log('Async Code');
}, 2000);
};
console.log('Hello World');
networkRequest();
console.log('The End');
// La segona funció té codi asíncron
function first() {console.log(1)}
function second() {
setTimeout(() => {
console.log(2)}, 0)} // 0 segons
function third() {console.log(3)}
first();
second();
third();
// Sempre eixirà 1 3 2
Programació asíncrona
Callback
// La segona funció tè codi asíncron
function first() {console.log(1)}
function second(callback) {setTimeout(() => {console.log(2); callback(); }, 0)}
function third() {console.log(3)}
first();
second(third);
// 1 2 3
Concepte de Callback
function fetchData(callback) {
setTimeout(() => {
const data = {name: "John", age: 30};
callback(data);
}, 3000);
}
// Execute function with a callback
fetchData(function(data) {
console.log(data);
});
console.log("Data is being fetched...");
Callback Hell
getData(function(a) {
getMoreData(a, function(b) {
getEvenMoreData(b, function(c) {
getEvenEvenMoreData(c, function(d) {
getFinalData(d, function(finalData) {
console.log(finalData);
});
});
});
});
});
Tasques i Microtasques
Aprofitar les tasques
let start = Date.now();
function count() {
// do a heavy job
for (let j = 0; j < 1e9; j++) {
i++;
}
console.log("Done in " + (Date.now() - start) + 'ms');
}
// count(); // Aquest bloqueja el navegador
setTimeout(count,0);
Fer una barra de progrés
document.addEventListener("DOMContentLoaded", () => {
let progress = document.querySelector("#progress");
let i = 0;
function count() {
// do a piece of the heavy job (*)
do {
i++;
progress.innerHTML = i;
} while (i % 1e3 != 0);
if (i < 1e7) { setTimeout(count); }
}
count();
});
S’ha de dividir en varis per a que puga renderitzar en mig
XMLHttpRequest
var req = new XMLHttpRequest();
req.open('GET', 'http://www.mozilla.org/', true);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) {
if(req.status == 200)
dump(req.responseText);
else
dump("Error loading page\n");
}
};
req.send(null);
Inicialitzar l'objecte en navegadors moderns.
Indiquem que volem que siga asíncrona amb el true
Quan canvie l'estat a 4 mirem si ha arribat i el mostrem.
APIs
API REST
API GraphQL
SDKs
Els SDK no són estàndards i dependen del proveidor. Per a ser més genèrics i aprendre la base anem a evitar-los en classe.
Esperar peticions asíncrones
https://developers.google.com/web/fundamentals/primers/promises?hl=es �https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Usar_promesas https://developer.mozilla.org/es/docs/Web/JavaScript/EventLoop#Ejecutar_hasta_completar https://www.digitalocean.com/community/tutorials/understanding-the-event-loop-callbacks-promises-and-async-await-in-javascript https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/async%20%26%20performance/ch3.md
const promise = new Promise((resolve, reject) => { // Funció executor
setTimeout(() => {
if (Math.random() > 0.5) { resolve("Resolving an asynchronous request!"); }
else { reject("Rejecting an asynchronous request!"); }
}, 2000);
});
promise.then((response) => { //.then si resol
console.log(response);
}).catch((response) => { // .catch si falla
console.log(response);
});
Promises
Encadenar promeses
Fetch
fetch('http://127.0.0.1:5500/datos.json')
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return; }
response.json().then(function(data) {
console.log(data);
}); } )
.catch(function(err) {
console.log('Fetch Error :-S', err);
});
Response
fetch('users.json').then(function(response) {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});
fetch("https://dwec-daw-default-rtdb.firebaseio.com/productos.json")
.then(response => response.json())
.then(data => console.log(data));
fetch("https://dwec-daw-default-rtdb.firebaseio.com/productos.json")
.then(response => response.text())
.then(data => console.log(data));
Encadenant promeses
function status(response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json(response) { return response.json() }
fetch('datos.json')
.then(status)
.then(json)
.then(function(data) {
console.log('Request succeeded with JSON response', data);
}).catch(function(error) {
console.log('Request failed', error);
}); https://stackoverflow.com/a/43082995
POST en fetch
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(function (data) {
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error);
});
let datos = {username: 'example'};
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body: JSON.stringify(datos)
})
.then(json)
.then(function (data) {
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error); });
FormData
let formElement = document.getElementById("myFormElement"); // Un formulari html
let formData = new FormData(formElement); // Constructor de formData amb un formulari
formData.append("serialnumber", serialNumber++); // Afegir més dades
formData.append("afile", fileInputElement.files[0]); // afegir un fitxer
fetch('http://localhost:3000/upload',{method: 'POST', body: formData});
Post FormData -> JSON con fetch
let data = new FormData(form);
let body = JSON.stringify(Object.fromEntries(data));
return fetch(url,{
method: 'POST',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body
}).then(response => response.json());
async function getUser() {
const response = await fetch('https://api.github.com/users/octocat')
const data = await response.json()
console.log(data)
}
// Execute async function
getUser()
Funcionalitat afegida en 2024!
Permet utilitzar await en qualsevol lloc sense crear funcions asíncrones.
const colors = fetch("../data/colors.json").then((response) => response.json());
export default await colors;
Carregar imatges en segon pla
<img src="placeholder.png" alt="${name}">
fetch(image_url)
.then(response => response.status == 200 ? response : Promise.reject(response.status))
.then(response => response.blob())
.then(imageBlob => {
let imageURL = URL.createObjectURL(imageBlob);
divCard.querySelector('img').src = URL.createObjectURL(imageBlob);
}).catch(error => console.log(error));
Construcció d’URLS
let country = `Saint Vincent & the Grenadines`;
fetch(`/api/cities?country=${country}`)
//"/api/cities?country=Saint Vincent & the Grenadines"
url = `/api/cities?${new URLSearchParams([[ 'country', country ]])}`
fetch(url)
//"/api/cities?country=Saint+Vincent+%26+the+Grenadines"
Websockets
WebSocket
let socket = new WebSocket("ws://localhost:8080");
socket.addEventListener("open", function(event) {
console.log("Conexión establecida.");
socket.send("¡Hola, servidor!");
});
socket.addEventListener("message", function(event) {
console.log("Mensaje recibido del servidor: " + event.data);
});
socket.addEventListener("error", function(error) {
console.log("Error en la conexión: " + error);
});
socket.addEventListener("close", function(event) {
console.log("Conexión cerrada. Código: " + event.code);
});
Tractament de les dades en Javascript
Passant dades a Json
class Apple {
constructor(type){
this.type = type;
this.color = "red";
}
}
var apple1 = new Apple('Golden'); // Es crea una instància
appleJson=JSON.stringify(apple1);
console.log(appleJson);
Convertint de JSON a objectes
class Hero{
constructor(name,car){
this.name = name; this.car=car;
}}
let heroJSON = '{"name":"Max","car":"V8"}';
let heroObject = JSON.parse(heroJSON);
let heroClass = Object.assign(new Hero, heroObject);
console.log(heroObject,heroClass);
Emmagatzemament en
el costat del client
Cookies
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2021 12:00:00 UTC; path=/";
Manipular Cookies
var x = document.cookie; // Llegir totes les cookies
// Modificar una cookie és sobreescriure
document.cookie = "username=John Smith; expires=Thu, 18 Dec 2021 12:00:00 UTC; path=/";
// Esborrar és fer que estiga expirada
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
LocalStorage
// Guardar
localStorage.setItem("lastname", "Smith");
// Obtenir
var lastname = localStorage.getItem("lastname");
// Esborrar
localStorage.removeItem("lastname");
indexedDB