Javascript 2
Exercice 1 : Comprendre les exceptions
function russianRoulette() {
if (Math.random() < 0.5) {
throw new Error("PAN");
}
}
try {
russianRoulette();
// Si aucune erreur n'est levée, le code continue ici
console.log("You survived :D");
} catch (e) {
// Si une erreur est levée, on entre dans ce bloc
console.log("You're dead :(");
}
Exercice 2 : Utiliser les promesses
Version avec .then() (Promesses classiques)
import axios from "axios";
axios
.get(
"https://raw.githubusercontent.com/JulienUsson/zz3-f2-js/refs/heads/master/api/users.json",
)
.then((response) => {
const users = response.data;
const frenchUsers = users.filter(
(user) => user.location.country === "France",
);
console.log("Utilisateurs en France :", frenchUsers);
})
.catch((err) => console.error("Erreur :", err));
console.log("Ceci s'affichera probablement AVANT la liste des utilisateurs.");
Version avec async / await
async function getFrenchUsers() {
try {
const response = await axios.get(
"https://raw.githubusercontent.com/JulienUsson/zz3-f2-js/refs/heads/master/api/users.json",
);
const frenchUsers = response.data.filter(
(user) => user.location.country === "France",
);
console.log("Utilisateurs en France (async) :", frenchUsers);
} catch (err) {
console.error(err);
}
}
getFrenchUsers();
Exercice 3 : Transformer un callback en promesse
Création du wrapper (Promisification)
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
Script avec async / await
async function joke() {
console.log("- Toc toc");
await wait(500);
console.log("- Qui est là?");
await wait(10000); // 10 secondes
console.log("- C'est Internet Explorer");
}
joke();
Exercice 4 : Gestion des erreurs
async function fetchWithHandling() {
try {
await axios.get(
"https://raw.githubusercontent.com/JulienUsson/zz3-f2-js/refs/heads/master/api/users.json",
);
console.log("Users loaded");
} catch (error) {
console.log("Something went wrong");
} finally {
console.log("Request finished");
}
}
fetchWithHandling();
Exercice 5 : Paralléliser avec Promise.all
async function fetchInParallel() {
try {
// On lance les deux promesses en même temps
const [res1, res2] = await Promise.all([
axios.get(
"https://raw.githubusercontent.com/JulienUsson/zz3-f2-js/refs/heads/master/api/users.json",
),
axios.get(
"https://raw.githubusercontent.com/JulienUsson/zz3-f2-js/refs/heads/master/api/users2.json",
),
]);
const allUsers = [].concat(res1.data).concat(res2.data);
console.log(`Nombre total d'utilisateurs : ${allUsers.length}`);
} catch (e) {
console.error("Échec d'une des requêtes");
}
}
Exercice 6 & 9 : Fonction Retry (avec backoff exponentiel)
Voici la version améliorée (Ex 9) qui couvre aussi l’exercice 6.
const wait = (ms) => new Promise((res) => setTimeout(res, ms));
async function retry(fn, attempts) {
try {
return await fn();
} catch (error) {
if (attempts <= 1) throw error;
// Calcul du délai exponentiel (Ex 9)
// Tentative 2 -> 1s, Tentative 3 -> 2s, Tentative 4 -> 4s
const delay = Math.pow(2, 4 - attempts) * 1000;
console.log(`Échec, nouvelle tentative dans ${delay}ms...`);
await wait(delay);
return retry(fn, attempts - 1);
}
}
Exercice 7 : Timeout avec Promise.race
On fait la course entre la requête et un chronomètre qui rejette la promesse.
function fetchWithTimeout(promise, ms) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timeout")), ms),
);
return Promise.race([promise, timeout]);
}
// Utilisation :
fetchWithTimeout(axios.get("..."), 2000)
.then(() => console.log("Succès"))
.catch((err) => console.log(err.message));
Exercice 8 : Promise.allSettled
Contrairement à Promise.all, cette fonction attend que toutes les promesses soient terminées (qu’elles aient réussi ou échoué).
async function checkMultipleApis() {
const requests = [
axios.get("URL_OK"),
axios.get("URL_ERREUR"),
axios.get("URL_OK_BIS"),
];
const results = await Promise.allSettled(requests);
const success = results.filter((r) => r.status === "fulfilled").length;
const failed = results.filter((r) => r.status === "rejected").length;
console.log(`Succès : ${success}, Échecs : ${failed}`);
}
Exercice 10 : Limiter la concurrence
C’est l’exercice le plus complexe. On utilise un “pool” de promesses actives.
async function parallelLimit(tasks, limit) {
const activeTasks = {}; // Objet pour suivre les tâches en cours
const allPromises = []; // Tableau pour stocker les promesses de résultats
for (let i = 0; i < tasks.length; i++) {
// 1. Si on atteint la limite de concurrence, on attend qu'une tâche finisse
if (Object.keys(activeTasks).length >= limit) {
// Promise.race attend un itérable (on transforme les valeurs de l'objet en tableau)
await Promise.race(Object.values(activeTasks));
}
// 2. On lance la tâche (une fonction retournant une promesse)
// On ajoute un .then() pour se retirer de l'objet activeTasks dès que c'est fini
const p = tasks[i]().then((res) => {
delete activeTasks[i];
return res; // On retourne le résultat pour Promise.all
});
// 3. On enregistre la promesse dans l'objet (pour le suivi de la limite)
activeTasks[i] = p;
// 4. On stocke la promesse dans notre tableau de résultats
allPromises.push(p);
}
// On attend que toutes les tâches stockées soient résolues
return Promise.all(allPromises);
}