Cyrille Perois
Lead front-end developer @ Wandi Teaches front-end development @ IUT Paris Descartes
Programmation web - Client riche
Ces requêtes sont souvent appelées « requêtes AJAX » (pour Asynchronous Javascript And XML) ou XHR (pour « XMLHttpRequest », l'objet historique sous-jacent). Toutefois, les données reçues en réponse ne sont pas forcément du XML. On utilise même plutôt JSON la plupart du temps.
JSON (pour JavaScript Object Notation) est un format de données textuelles qui s'inspire de la syntaxe des objets en JS. Voir la page Wikipédia correspondante pour plus d'informations
const result = fetch("url/to/resource")
console.log(result)
La fonction fetch permet d'envoyer une requête HTTP de manière non-bloquante. Elle retourne une Promise résolue avec un objet de type Response
Attends, une Pr... quoi ?!
Quand on écrit un bout de code, on s'attend à ce que les lignes soient exécutées les une après les autres, dans l'ordre. On dit que le code est "synchrone" : une ligne n'est exécutée qu'une fois que la ligne précédente a terminé son exécution
const a = 10
const b = 42
const result = add(a, b)
console.log(result)
// => 52
Mais du code synchrone ne permet pas de paralléliser deux bouts de code qui n'ont pas besoin l'un de l'autre
/*
* getCategories n'est exécutée qu'après que getProducts ait
* terminé son exécution.
* Pourtant, les 2 fonctions ne sont pas correlées, donc on
* pourrait imaginer de les exécuter en parallèle
*/
const products = getProducts()
showProducts(products)
const categories = getCategories()
showCategories(categories)
Dans un langage comme Java, on aurait tendance à lancer 2 threads qui pourraient faire les traitements en parallèle.
Mais...
JavaScript est monothreadé.
De plus, dans le navigateur, notre code JS tourne dans le même thread que toute l'interface du navigateur. Donc un bout de code "bloquant" bloque tout le navigateur
L'objet Promise représente la "promesse" qu'un appel asynchrone va produire un résultat (valeur ou erreur) dans le futur.
state: pending value: undefined
state: fulfilled value: 42
resolve(42)
state: rejected reason: error
reject(error)
Le mot-clef async est lié à la définition d'une fonction. Il définit la fonction comme étant asynchrone.
Cela a deux implications :
const asyncFunction = async () => {
/* Utilisation d'APIs asynchrones */
return 42
}
const promise = asyncFunction()
Le mot-clef await s'utilise sur une Promise. Il permet de "mettre en pause" la fonction dans laquelle il se trouve, jusqu'à ce que la Promise soit fulfilled ou rejected.
Il ne peut être utilisé que dans une fonction asynchrone
const asyncFunction = async () => {
console.log("Before")
await somethingReturningAPromise()
console.log("After")
}
try {
const response = await fetch("url/to/resource")
const data = await response.json()
console.log(data)
} catch (err) {
console.error(error)
}
Le serveur peut nous renvoyer une réponse dans divers formats. Il faut qu'on formate la réponse dans le format attendu
Une fois que le corps de la réponse a été formaté, on ne peut pas le formater dans un autre format
const response = await fetch("url/to/resource", {
headers: {
Authentication: "authentication token"
}
})
Attention, tous les headers ne sont pas autorisés : voir la liste des headers interdits dans la spécification
const response = await fetch("url/to/resource", {
method: "POST" // "GET" ou "POST" ou "PUT" ou "DELETE"
})
const response = await fetch("url/to/resource", {
method: "POST",
body: "some data"
})
Pour envoyer des données dans le corps de la requête, on peut passer une chaîne de caractères au paramètre body de la requête
Le header Content-Type est défini à "text/plain;charset=UTF-8" par défaut
const response = await fetch("url/to/resource", {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8"
},
body: JSON.stringify({ firstname: "Cyrille", role: "Prof" })
})
On peut envoyer les données à partir d'un objet JS en le transformant en JSON
Le header Content-Type doit être défini à "application/json;charset=utf-8" dans ce cas, pour indiquer au serveur que le corps de la requête contient du JSON
const form = document.querySelector("form")
const data = new FormData(form)
const response = await fetch("url/to/resource", {
method: "POST",
body: data
})
On peut aussi utiliser un objet FormData pour récupérer les données contenus dans un formulaire et les envoyer
Lorsqu'on utilise un objet FormData dans le corps de la requête, le header Content-Type est ajouté automatiquement
By Cyrille Perois