Promesses JavaScript

"Je promets un résultat !"

"Produire du code" désigne un code qui peut prendre du temps.

"Consommer du code" désigne un code qui doit attendre le résultat.

Une promesse est un objet qui relie le code de production et le code de consommation.

L' objet Promise représente l'achèvement ou l'échec d'une opération asynchrone et ses résultats.

Une promesse peut avoir 3 états :

en attente état initial
rejetée opération échouée
remplie opération terminée

Exemple

// Créer un objet Promise
let myPromise = new Promise(function(myResolve, myReject) {
let result = true;

// Le code qui peut prendre du temps va ici

if (result == true) {
myResolve("OK");
} else {
myReject("Erreur");
}
});

// Utiliser then() pour afficher le résultat
myPromise.then(x => myDisplay(x), x => myDisplay(x));

Essayez-le vous-même »

Objet Promise JavaScript

Une promesse contient à la fois le code de production et les appels au code de consommation :

Syntaxe de la promesse

let myPromise = new Promise(function(myResolve, myReject) {
// "Code de production" (peut prendre du temps)

myResolve(); // quand c'est réussi
myReject(); // quand il y a une erreur
});

// "Code de consommation" (doit attendre une promesse remplie)
myPromise.then(
function(value) { /* code si réussi */ },
function(error) { /* code si erreur */ }
);

Lorsque le code de production obtient le résultat, il doit appeler l'un des deux rappels :

Quand Appel
Succès myResolve(valeur du résultat)
Erreur myReject(objet d'erreur)

Propriétés de l'objet Promise

Un objet Promise JavaScript peut être :

  • En attente
  • Rempli
  • Rejeté

L'objet Promise prend en charge deux propriétés : état et résultat .

Tant qu'un objet Promise est "en attente" (en cours d'exécution), le résultat est indéfini.

Lorsqu'un objet Promise est "rempli", le résultat est une valeur.

Lorsqu'un objet Promise est "rejeté", le résultat est un objet d'erreur.

myPromise.state myPromise.result
"en attente" indéfini
"rempli" une valeur de résultat
"rejeté" un objet d'erreur

Vous ne pouvez pas accéder aux propriétés de la promesse état et résultat .

Vous devez utiliser une méthode Promise pour gérer les promesses.


Comment utiliser Promise

Voici comment utiliser une promesse :

myPromise.then(
function(value) { /* code si réussi */ },
function(error) { /* code si erreur */ }
);

Promise.then() prend deux arguments, un rappel pour le succès et un autre pour l'échec.

Les deux sont optionnels, vous pouvez donc ajouter un rappel pour le succès ou l'échec uniquement.

Exemple

function myDisplayer(some) {
document.getElementById("demo").innerHTML = some;
}

let myPromise = new Promise(function(myResolve, myReject) {
let x = 0;

// Le code de production (cela peut prendre du temps)

if (x == 0) {
myResolve("OK");
} else {
myReject("Erreur");
}
});

myPromise.then(
function(value) {myDisplayer(value);},
function(error) {myDisplayer(error);}
);

Essayez-le vous-même »



Exemples de promesses JavaScript

Pour démontrer l'utilisation des promesses, nous allons utiliser les exemples de rappel du chapitre précédent :

  • Attendre un délai
  • Attendre un fichier

Attendre un délai

Exemple utilisant un rappel

setTimeout(function() { myFunction("Je t'aime !!!"); }, 3000);

function myFunction(value) {
document.getElementById("demo").innerHTML = value;
}

Essayez-le vous-même »

Exemple utilisant une promesse

let myPromise = new Promise(function(myResolve, myReject) {
setTimeout(function() { myResolve("Je t'aime !!"); }, 3000);
});

myPromise.then(function(value) {
document.getElementById("demo").innerHTML = value;
});

Essayez-le vous-même »


Attendre un fichier

Exemple utilisant un rappel

function getFile(myCallback) {
let req = new XMLHttpRequest();
req.open('GET', "mycar.html");
req.onload = function() {
if (req.status == 200) {
myCallback(req.responseText);
} else {
myCallback("Erreur : " + req.status);
}
}
req.send();
}

getFile(myDisplayer);

Essayez-le vous-même »

Exemple utilisant une promesse

let myPromise = new Promise(function(myResolve, myReject) {
let req = new XMLHttpRequest();
req.open('GET', "mycar.html");
req.onload = function() {
if (req.status == 200) {
myResolve(req.response);
} else {
myReject("Fichier non trouvé");
}
};
req.send();
});

myPromise.then(
function(value) {myDisplayer(value);},
function(error) {myDisplayer(error);}
);

Essayez-le vous-même »


JavaScript Promise.allSettled()

La méthode Promise.allSettled() renvoie une seule promesse à partir d'une liste de promesses.

Exemple

// Créer une promesse
const myPromise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 200, "Roi");
});

// Créer une autre promesse
const myPromise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "Reine");
});

// Régler toutes
Promise.allSettled([myPromise1, myPromise2]).then((results) =>
results.forEach((x) => myDisplay(x.status)),
);
Essayez-le vous-même »

Remarque

Promise.allSettled() signifie "Exécutez simplement toutes les promesses. Je me fiche des résultats".

Support des navigateurs

Promise.allSettled() est une fonctionnalité ES2020 .

ES2020 est entièrement pris en charge dans tous les navigateurs modernes depuis septembre 2020 :

Chrome
85
Edge
85
Firefox
79
Safari
14
Opera
71
Août 2020 Août 2020 Mars 2020 Sept 2020 Sept 2020


JavaScript Promise.withResolvers()

Promise.withResolvers() est une méthode statique qui simplifie la création et la gestion des promesses.

Promise.withResolvers() fournit un moyen plus pratique d'accéder aux fonctions resolve et reject associées à une promesse en dehors de sa fonction exécuteur.

Au lieu du modèle de constructeur traditionnel new Promise((resolve, reject) => { ... }) , Promise.withResolvers() renvoie un objet contenant :

  • promise : L'instance de promesse nouvellement créée
  • resolve : Une fonction pour remplir la promesse avec une valeur
  • reject : Une fonction pour rejeter la promesse avec une raison (erreur)

Exemple

<p id="demo">En attente...</p>

<script>
const {promise, resolve, reject} = Promise.withResolvers();

// Vous pouvez maintenant utiliser 'resolve' et 'reject' n'importe où
// dans votre code pour contrôler l'état de 'promise'.

// Simuler un travail asynchrone
setTimeout(() => {
const success = Math.random() > 0.5;
if (success) {
resolve("Opération réussie !");
} else {
reject("Opération échouée !");
}
}, 1000);

// Mettre à jour l'interface utilisateur lorsque la promesse se termine
promise
.then((message) => {
document.getElementById("demo").innerHTML = message;
})
.catch((error) => {
document.getElementById("demo").innerHTML = error;;
});
</script>
Essayez-le vous-même »

Exemple expliqué

  • Le <p id="demo"> montre initialement "En attente..."
  • Après 1 seconde, la promesse se résout ou se rejette
  • Le résultat est écrit dans "demo"

Le code pour simuler un travail asynchrone peut être simplifié à :

// Simuler un travail asynchrone
setTimeout(() => {
Math.random() > 0.5
? resolve("Opération réussie !")
: reject("Opération échouée !");
}, 1000);

Le code then / catch peut être simplifié à :

// Définir le texte dans then/catch, mettre à jour le DOM dans finally
promise
.then((message) => text = message)
.catch((error) => text = error)
.finally(() => {
document.getElementById("demo").innerHTML = text;
});
Essayez-le vous-même »

Exemple expliqué

  • .then() ou .catch() définissent la variable texte
  • .finally() s'exécute toujours en dernier, peu importe le succès ou l'échec
  • Le DOM est mis à jour exactement une fois, proprement et de manière fiable

Utiliser async/await est le plus propre :

// Utiliser async/await pour gérer la promesse
(async () => {
try {
text = await promise; // Attendre la résolution
} catch (err) {
text = err; // Gérer le rejet
}
// Mettre à jour l'interface utilisateur après la fin de la promesse
document.getElementById("demo").innerHTML = text;
})();
Essayez-le vous-même »

Exemple expliqué

  • async/await rend le code asynchrone semblable à du code synchrone
  • Le DOM est mis à jour après que la promesse se résout ou se rejette
  • L'interface utilisateur se met à jour à un seul endroit (pas d'appels innerHTML dupliqués)