Sujet 2

  1. Bienvenue au 2e sujet
  2. Exécution asynchrone
    1. chat.html
    2. Bouton
    3. Correction
    4. Boucle infinie
    5. Temps d’exécution
    6. Boucle d'événements
    7. Boucle d'événements - questions
    8. Boucle d'événements et JS
    9. JS bloquant
    10. Souris
    11. JS et Affichage
  3. Exécution différée
    1. Attendre
    2. Attendre setTimeout
    3. Ordre d'affichage
    4. setTimeout explications
    5. Exécution différée: faire une action plus tard
    6. Course
    7. 1er déplacement
    8. Correction
    9. 2ème déplacement
    10. Correction
    11. 3ème déplacement
    12. Correction
    13. Callback Hell
  4. Promesses
    1. Range ta chambre
    2. range_ta_chambre()
    3. Valeur de retour
    4. Utilisation promesse
    5. Catch
    6. Enchaîner then() et catch()
    7. Plusieurs promesses
    8. Deux rangements successifs
    9. Correction
    10. 3 rangements
    11. Correction
    12. Le « Callback hell » du rangement
    13. attendre()
    14. Attendre 4 fois
    15. Correction
    16. Course chat / souris en promesses
    17. Course promesses
    18. Correction
  5. async / await
    1. async
    2. await
    3. Course chat / souris avec await
    4. script et await
    5. course await
    6. Correction

1. Bienvenue au 2e sujet

1.1 Bienvenue au 2e sujet

Pour votre progression, c'est très important de finir le sujet précédent avant de commencer celui-ci.

Vous devez travailler connectés (lien « Connexion » en haut à droite de la page). Sinon, vous rencontrerez des problèmes d'avancement et vous risquez d'être comptés absent. En étant connectés vous retrouverez l'endroit où vous en étiez à la séance suivante.

2. Exécution asynchrone

2.1 Exécution asynchrone

Le JS a une particularité: on exécute des choses de manière « asynchrone ».
On va apprendre ce que ça veut dire et comment l'utiliser.

Exécution asynchrone

2.2 chat.html

Sur cette page, une image avec un chat est affichée. Une animation CSS bouge l'image horizontalement.

Créez le fichier chat.html et ouvrez-le:

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Chat</title>
<style>
body { max-width: 40em; }
#bouton { font-size: 20px; }
#chat {
position: absolute;
left: 0px;
top: 0px;
width: 200px;
animation-duration: 5s;
animation-name: chatbouge;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: linear;
}
@keyframes chatbouge {
from { left: 0px; }
to { left: 400px;}
}

</style>
</head>
<body>
<h1>Ceci est une page</h1>
<p>Bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla </p>
<p><img id="chat" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/chat.png"/></p>
<p>Bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla </p>
<button id="bouton">Bouton</button>
<p>Bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla </p>
<script>
</script>
</body>
</html>



Exécution asynchrone

2.3 Bouton

Quand l'utilisateur clique sur le bouton, affichez "click" dans la console.

Écrivez votre code dans la balise <script>

Exécution asynchrone

2.4 Correction


<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Chat</title>
<style>
body { max-width: 40em; }
#bouton { font-size: 20px; }
#chat {
position: absolute;
left: 0px;
top: 0px;
width: 200px;
animation-duration: 5s;
animation-name: chatbouge;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: linear;
}
@keyframes chatbouge {
from { left: 0px; }
to { left: 400px;}
}

</style>
</head>
<body>
<h1>Ceci est une page</h1>
<p>Bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla </p>
<p><img id="chat" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/chat.png"/></p>
<p>Bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla </p>
<button id="bouton">Bouton</button>
<p>Bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla </p>
<script>
document.getElementById('bouton').addEventListener('click',()=>{
console.log('click');
});

</script>
</body>
</html>

Exécution asynchrone

2.5 Boucle infinie

On va voir ce qui se passe si on bloque l’exécution du JS.

Dans la fonction anonyme qui est appelée quand on appuie sur le bouton, ajoutez une boucle infinie après console.log('click') :

while(true);

La condition du while est toujours vraie. Le point-virgule juste après indique qu'il n'y a rien à faire.
Le JS exécute ce code en boucle et reste bloqué à cet endroit du code.

Que se passe-t-il quand on clique sur le bouton ?

Exécution asynchrone

2.6 Temps d’exécution

Si le JS bloque, la page devient inutilisable.
C'est un principe important: dans le navigateur, le JS ne doit jamais bloquer. Il doit être « non-bloquant »

Enlevez la boucle infinie.

Ajoutons un peu de code pour voir combien de temps notre code met à être exécuté:

Vous devriez avoir ceci:

		<script>
let debut=Date.now();
window.getComputedStyle(document.getElementById('chat')).top;
document.getElementById('chat').style.left='400px';
document.getElementById('bouton').addEventListener('click',()=>{
console.log('click');
});
console.log('Durée:',(Date.now()-debut)+'ms');
</script>

Ouvrez la console et rechargez la page.
Quelles affirmations sont vraies ?

Exécution asynchrone

2.7 ¤ Boucle d'événements

On voit donc que le code JS s’exécute très vite, en quelques millisecondes.
L'utilisateur ne s’aperçoit pas de ce blocage très court.
A la fin de notre code JS (fin du <script>), on rend la main au navigateur.

Que fait le navigateur ensuite ?
Le navigateur passe la plupart de son temps dans la « boucle d'événements »... à ne rien faire.
De temps en temps (au plus toutes les 16 millisecondes), il se rend compte que quelque-chose à changé (par exemple, le chat animé a bougé) et qu'il est temps de mettre à jour l'affichage.
Alors, il met à jour l'affichage.

Boucle d'événements

Execution JS

xyz

Affichage

Exécution asynchrone

2.8 Boucle d'événements - questions

Quelles affirmations sont vraies ?

Exécution asynchrone

2.9 ¤ Boucle d'événements et JS

Lorsqu'on appuie sur le bouton, le navigateur ajoute une tache JS à exécuter dans la liste (à gauche de l'animation ci-dessous).
Lorsque ce code JS a fini de s'exécuter il rend la main au navigateur, qui retourne dans la boucle d'événements.
Plus tard, il rafraîchit l'affichage si nécessaire (l'image du chat bouge).

Boucle d'événements

Execution JS

xyz

Affichage

Exécution asynchrone

2.10 ¤ JS bloquant

Lorsque le JS bloque, le navigateur reste coincé et ne retourne pas à la boucle d'événements.

Remettons la boucle infinie:

              while(true);

Boucle d'événements

Execution JS

xyz

Affichage

Exécution asynchrone

2.11 Souris

Dans le HTML, juste après le chat, ajoutez l'image suivante en utilisant id="souris":

Dans la partie CSS ajoutez:

			#souris {
position: absolute;
top: 100px;
left: 400px;
}

Dans la partie JS, lorsque l'utilisateur clique sur le bouton, ajoutez:

  	                  const souris=document.getElementById('souris');
souris.style.top='150px';
souris.style.top='300px';
souris.style.top='400px';

Lisez le JS et regardez l'affichage.
Que voyez vous à l'écran quand vous cliquez sur le bouton ?

Exécution asynchrone

2.12 ¤ JS et Affichage

Essayons de comprendre le déplacement de l'image de la souris.

Boucle d'événements

Execution JS

xyz

Affichage

3. Exécution différée

3.1 Exécution différée

Dans les pages suivantes, on va creuser la notion d’exécution différée.

Exécution différée

3.2 Attendre

Supposons qu'on veuille attendre 5 secondes avant d'afficher « bonjour » sur la console.

let d=Date.now();
while(Date.now()<d+5000);
console.log('bonjour')

Quelles affirmations sont vraies ?
(N’hésitez pas à essayer le code)

Exécution différée

3.3 Attendre setTimeout

Le code précédent n'est pas une bonne solution. Il bloque le navigateur.

Essayons une autre approche, avec setTimeout :

console.log('début');
setTimeout(()=>{
       console.log('bonjour');
    }, 5000);
console.log('fin')

setTimeout dit au navigateur d'appeler une fonction après une durée donnée (ici 5000ms)

Quelles affirmations sont vraies ?
(N’hésitez pas à essayer le code)

Exécution différée

3.4 Ordre d'affichage

console.log('début');
setTimeout(()=>{
       console.log('bonjour');
    }, 5000);
console.log('fin')

Quel est l'ordre d'affichage ?

Exécution différée

3.5 ¤ setTimeout explications

Explications:

console.log('début');
setTimeout(()=>{
       console.log('bonjour');
    }, 5000);
console.log('fin')

Boucle d'événements

Execution JS

xyz

Affichage

Exécution différée

3.6 ¤ Exécution différée: faire une action plus tard

Le code suivant

setTimeout(xyz, 1234)  

permet de dire au navigateur « Tiens, prends cette fonction xyz et exécute-là plus tard » (dans 1234 ms).
On a fourni au navigateur une action qu'il doit faire plus tard.

Le code suivant

document.addEventListener('click',xyz);

permet de dire au navigateur « Tiens, prends cette fonction xyz et exécute-là plus tard » (quand l'utilisateur clique)
On a fourni au navigateur une action qu'il doit faire plus tard.

En JS, on cherche souvent à faire exécuter des actions plus tard. Ces actions sont des fonctions.
C'est pour ça qu'on a autant besoin de manipuler des fonctions. Les fonctions anonymes sont une manière pratique (mais pas indispensable) de le faire.
Une fonction qu'on fournit pour être appelée plus tard s’appelle un « callback »

Exécution différée

3.7 Course

Créez le fichier course.html suivant:

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Course</title>
<style>
#chat {
position: absolute;
left: 0px;
top: 0px;
width: 200px;
transition: left 1s,top 1s;
}
#souris {
position: absolute;
left: 400px;
top: 100px;
transition: left .5s,top .5s;
}
</style>
</head>
<body>
<img id="chat" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/chat.png"/>
<img id="souris" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/souris.svg"/>
<script>
</script>
</body>
</html>


Exécution différée

3.8 1er déplacement

Dans la balise <script>, écrivez le code pour qu'une seconde après le chargement de la page, le chat se déplace aux coordonnées (300,100) et la souris à (400,300).

Les coordonnées correspondent à (left,top). N'oubliez pas les 'px'.

Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:

Exécution différée

3.9 Correction

		<script>
const chat =document.getElementById('chat' );
const souris=document.getElementById('souris');
setTimeout(()=>{
chat.style.left='300px';
chat.style.top ='100px';
souris.style.left='400px';
souris.style.top ='300px';
},1000);
</script>

Exécution différée

3.10 2ème déplacement


Faites en sorte qu'après le premier déplacement, le chat et la souris se déplacent à nouveau.
Cette fois le chat se déplace aux coordonnées (240,200) et la souris à (200,400).

Contrainte: n'utilisez setTimeout qu’avec la valeur 1000.

Exécution différée

3.11 Correction

		<script>
const chat =document.getElementById('chat' );
const souris=document.getElementById('souris');
setTimeout(()=>{
chat.style.left='300px';
chat.style.top ='100px';
souris.style.left='400px';
souris.style.top ='300px';
setTimeout(()=>{
chat.style.left='250px';
chat.style.top ='200px';
souris.style.left='200px';
souris.style.top ='400px';
},1000);
},1000);
</script>

Exécution différée

3.12 3ème déplacement

Faites en sorte qu'après le deuxième déplacement, le chat et la souris se déplacent à nouveau.
Cette fois le chat se déplace aux coordonnées (360,450) et la souris à (500,600).

Même contrainte: n'utilisez setTimeout qu’avec la valeur 1000.

Exécution différée

3.13 Correction

		<script>
const chat =document.getElementById('chat' );
const souris=document.getElementById('souris');
setTimeout(()=>{
chat.style.left='300px';
chat.style.top ='100px';
souris.style.left='400px';
souris.style.top ='300px';
setTimeout(()=>{
chat.style.left='250px';
chat.style.top ='200px';
souris.style.left='200px';
souris.style.top ='400px';
setTimeout(()=>{
chat.style.left='360px';
chat.style.top ='450px';
souris.style.left='500px';
souris.style.top ='600px';
},1000);
},1000);
},1000);
</script>

Exécution différée

3.14 ¤ Callback Hell

Pour enchaîner dans le temps des opérations, on a dû emboîter des fonctions. Ce n'est pas très lisible.
Ici, on n'en a emboîté que 3, mais en pratique, ça peut être bien pire.

Cette situation arrive souvent en JS quand on veut enchaîner des opérations qui sont décalées dans le temps.
Cette situation a un nom: « Callback Hell ».

Pour résoudre ce problème et faciliter la vie des développeurs, le JS propose deux outils, liés:


4. Promesses

4.1 ¤ Promesses

En JS, une promesse (Promise) est un objet qui représente une opération future.
Il sert à faciliter l’exécution différée.
Dans ce cours, on va apprendre à utiliser des  promesses, mais pas à en créer nous mêmes (c'est moins courant).

Commençons par un exemple.

Promesses

4.2 Range ta chambre

Créez le fichier range-ta-chambre.html suivant:

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Range ta chambre</title>
</head>
<body>
<img src="https://moodle.iutv.univ-paris13.fr/img/bjs2/chambre.jpg"/>
<script src="https://moodle.iutv.univ-paris13.fr/img/bjs2/bjs2-js-lib.js"></script>
<script>
</script>
</body>
</html>


Promesses

4.3 range_ta_chambre()

Dans <script> appelez la fonction range_ta_chambre avec comme paramètre un nom.
Observez ce qu'il se passe dans la console. Rechargez la page plusieurs fois.


Promesses

4.4 Valeur de retour

La fonction range_ta_chambre('Tom') retourne une valeur.
Mettez cette valeur dans une nouvelle variable appelée "p" et affichez-là dans la console.

Quel est le type de "p" ?
(regardez dans la console)

Promesses

4.5 ¤ Utilisation promesse

			const p=range_ta_chambre('Tom');
console.log(p);
« p » est une promesse.
La fonction range_ta_chambre ne range pas la chambre toute de suite.
Dans l'immédiat, elle nous donne juste une promesse: de ranger sa chambre, plus tard.
On sait bien que ce type de promesse pourra être tenue ... ou pas.

En JS, une promesse peut avoir trois états:
Ranger sa chambre peut prendre du temps ...
Au début, « p » est « en attente ». Après quelques secondes elle deviendra « tenue » ou « rompue ».
On ne manipule pas ces états directement... mais c'est très important de comprendre qu'ils existent.

then

Comme on l'a vu, on ne peut pas bloquer le JS en attendant que cette promesse aboutisse.
On va donc fournir à la promesse une fonction (callback) qu'elle pourra appeler plus tard.
Pour ça, l'objet « p » a une méthode appelée « then ».
« then » prend en paramètre une fonction qui sera appelée si la promesse est tenue.

Que faut-il écrire pour afficher « Trés bien! » dans la console quand la promesse « p » est tenue ?

(Essayez dans votre <script> ou dans la console avant de répondre)
(utilisez une fonction fléchée, sans paramètre, et avec des accolades {...} )

Promesses

4.6 ¤ Catch

Comment faire pour réagir si la promesse n'est pas tenue ?

Comme la méthode then(...), les promesses ont une méthode catch(...), qui prend une fonction en paramètre:

            const p=range_ta_chambre('Tom');
            p.catch(()=>{console.log('Tu es vilain!');});
Essayez dans votre navigateur.

Promesses

4.7 ¤ Enchaîner then() et catch()

La méthode p.then(...) renvoie une nouvelle promesse.

On pourrait la mettre dans une nouvelle variable « p2 », comme ceci:

let p=range_ta_chambre('Tom');
let p2=p.then(()=>{console.log('Trés bien!');});

Mais, le plus souvent, on l'utilisera directement, pour enchaîner avec catch:

p.then(()=>{console.log('Trés bien!');}).catch(()=>{console.log('Tu es vilain!');});

La même chose en 2 lignes:

p.then( ()=>{console.log('Trés bien!');})
.catch(()=>{console.log('Tu es vilain!');});

Très souvent, on ne met pas non plus la première promesse (p) dans une variable. Ce qui donne:

range_ta_chambre('Tom')
.then( ()=>{console.log('Trés bien!');})
.catch(()=>{console.log('Tu es vilain!');});
Essayez le code précédent. Vous ne devriez plus avoir de message d’erreur.

Promesses

4.8 Plusieurs promesses

Effacez tout le code dans <script>
Appelez 3 fois la fonction range_ta_chambre avec des noms différents.

Qu'est-ce qui se passe ?

Promesses

4.9 Deux rangements successifs

Effacez tout le code dans <script>

On veut que deux personnes rangent leur chambre.
La deuxième ne doit commencer à ranger sa chambre qu'après que la première ait réussi à ranger la sienne.

Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:

Promesses

4.10 Correction


range_ta_chambre('Tom')
    .then(()=>{range_ta_chambre('Paul')});


Promesses

4.11 3 rangements

Maintenant, on veut que 3 personnes rangent leur chambre successivement.
La fonction range_ta_chambre peut prendre un 2e paramètre, la probabilité de réussite.
Mettez-le à 1, pour faciliter la lecture.

Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:

Promesses

4.12 Correction

 			range_ta_chambre('Tom',1).then(()=>{
range_ta_chambre('Paul',1).then(()=>{
range_ta_chambre('Jean',1);
})
});

Promesses

4.13 ¤ Le « Callback hell » du rangement

			range_ta_chambre('Tom',1).then(()=>{
range_ta_chambre('Paul',1).then(()=>{
range_ta_chambre('Jean',1);
})
});

On se retrouve dans la situation du chat poursuivant la souris: des fonctions, dans des fonctions, dans des fonctions...

Solution

Si la fonction (ici anonyme) fournie à .then() retourne une promesse, alors on peut enchaîner les appels à .then() :

			range_ta_chambre('Tom',1)
.then(()=>{return range_ta_chambre('Paul',1);})
.then(()=>{return range_ta_chambre('Jean',1);})

C'est plus propre.

Promesses

4.14 attendre()

La fonction attendre(d) renvoie une promesse, qui est toujours tenue (elle n'échoue jamais). Elle aboutit après une durée de « d » millisecondes. Par exemple: attendre(5000) aboutit après 5000 ms.

Que faut-il écrire pour afficher « ok » après 2 secondes, en utilisant « attendre » ?
(Utilisez une fonction fléchée, sans paramètre, avec des accolades. N'utilisez pas setTimeout)
Essayez avant de répondre.

Promesses

4.15 Attendre 4 fois

Affichez successivement ok1, ok2, ok3 et ok4 sur la console, avec  2 secondes de délai.

Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:


Promesses

4.16 Correction

			attendre(2000)
.then(()=>{console.log('ok1');return attendre(2000);})
.then(()=>{console.log('ok2');return attendre(2000);})
.then(()=>{console.log('ok3');return attendre(2000);})
.then(()=>{console.log('ok4');return attendre(2000);})

Promesses

4.17 Course chat / souris en promesses

Créez le fichier course-promesses.html suivant:
(pour l'instant c'est une copie de course.html)
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Course promesses</title>
<style>
#chat {
position: absolute;
left: 0px;
top: 0px;
width: 200px;
transition: left 1s,top 1s;
}
#souris {
position: absolute;
left: 400px;
top: 100px;
transition: left .5s,top .5s;
}
</style>
</head>
<body>
<img id="chat" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/chat.png"/>
<img id="souris" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/souris.svg"/>
<script>
const chat =document.getElementById('chat' );
const souris=document.getElementById('souris');
setTimeout(()=>{
chat.style.left='300px';
chat.style.top ='100px';
souris.style.left='400px';
souris.style.top ='300px';
setTimeout(()=>{
chat.style.left='250px';
chat.style.top ='200px';
souris.style.left='200px';
souris.style.top ='400px';
setTimeout(()=>{
chat.style.left='360px';
chat.style.top ='450px';
souris.style.left='500px';
souris.style.top ='600px';
},1000);
},1000);
},1000);
</script>
</body>
</html>

Promesses

4.18 Course promesses

Re-écrivez le code dans <script> en utilisant la fonction attendre() et sans utiliser setTimeout()

Pour pouvoir utiliser attendre(), ajoutez la ligne suivante avant le  <script> principal:

        <script src="https://moodle.iutv.univ-paris13.fr/img/bjs2/bjs2-js-lib.js"></script>

Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:


Promesses

4.19 Correction

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Course promesses</title>
<style>
#chat {
position: absolute;
left: 0px;
top: 0px;
width: 200px;
transition: left 1s,top 1s;
}
#souris {
position: absolute;
left: 400px;
top: 100px;
transition: left .5s,top .5s;
}
</style>
</head>
<body>
<img id="chat" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/chat.png"/>
<img id="souris" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/souris.svg"/>
<script src="https://moodle.iutv.univ-paris13.fr/img/bjs2/bjs2-js-lib.js"></script>
<script>
const chat =document.getElementById('chat' );
const souris=document.getElementById('souris');
attendre(1000)
.then(()=>{
chat.style.left='300px';
chat.style.top ='100px';
souris.style.left='400px';
souris.style.top ='300px';
return attendre(1000);
})
.then(()=>{
chat.style.left='250px';
chat.style.top ='200px';
souris.style.left='200px';
souris.style.top ='400px';
return attendre(1000);
})
.then(()=>{
chat.style.left='360px';
chat.style.top ='450px';
souris.style.left='500px';
souris.style.top ='600px';
return attendre(1000);
})
</script>
</body>
</html>

Don't trust javascript programmers
All they do is promises but they never callback.


5. async / await

5.1 ¤ async / await

Les promesses aident à simplifier le code, mais restent lourdes à utiliser.
Ceci étant, elles permettent (parfois) l'utilisation de « await »... qui simplifie énormément le code 😀

« await » permet de faire comme si on attendait, sans réellement bloquer le JS, donc en rendant la main au navigateur.

console.log('bonjour');
await attendre(5000);
console.log("ceci s'affiche vraiment 5s après !!! :-)");

Explication:


async / await

5.2 ¤ async

await est vraiment très pratique...  et a un coté un peu « magique »

await fait des choses « bizarres ». Il arrête l’exécution en plein milieu d'une fonction, pour la reprendre, plus tard, au même endroit.
Pour que ça puisse marcher, la fonction qui contient await doit être un peu particulière. Elle doit être déclaré comme « async »:

async function exemple() {
console.log('bonjour'); await attendre(5000); console.log("ceci s'affiche vraiment 5s après !!! :-)");
}
Petit détail:
Vous ne pouvez pas utiliser await directement dans un script normal (sauf si vous mettez await dans une fonction async):
<script>    
    await attendre(5); // erreur !
</script>
Il faut ajouter type="module"
<script type="module">    
    await attendre(5); // ok
</script>
ATTENTION: 2023:
<script type="module"> Ne fonctionne pas dans les anciennes versions (<89) de Firefox  installées dans certaines salles de l'IUT. Vous devez ajouter une fonction "async" autour du code qui utilise "await" et appeler la fonction.
Exemple:
<script>
     (async function(){
           // votre code
           await exemple();
     })();
</script>

async / await

5.3 ¤ await

Voyons le déroulement de « await »:

Boucle d'événements

Execution JS

xyz

Affichage

async / await

5.4 Course chat / souris avec await

Créez le fichier course-await.html suivant:
(pour l'instant c'est une copie de course-promesses.html)

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Course promesses</title>
<style>
#chat {
position: absolute;
left: 0px;
top: 0px;
width: 200px;
transition: left 1s,top 1s;
}
#souris {
position: absolute;
left: 400px;
top: 100px;
transition: left .5s,top .5s;
}
</style>
</head>
<body>
<img id="chat" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/chat.png"/>
<img id="souris" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/souris.svg"/>
<script src="https://moodle.iutv.univ-paris13.fr/img/bjs2/bjs2-js-lib.js"></script>
<script>
const chat =document.getElementById('chat' );
const souris=document.getElementById('souris');
attendre(1000)
.then(()=>{
chat.style.left='300px';
chat.style.top ='100px';
souris.style.left='400px';
souris.style.top ='300px';
return attendre(1000);
})
.then(()=>{
chat.style.left='250px';
chat.style.top ='200px';
souris.style.left='200px';
souris.style.top ='400px';
return attendre(1000);
})
.then(()=>{
chat.style.left='360px';
chat.style.top ='450px';
souris.style.left='500px';
souris.style.top ='600px';
return attendre(1000);
})
</script>
</body>
</html>


async / await

5.5 script et await

Comment faut-il récrire la balise ouvrante <script> pour pouvoir utiliser « await » à l'intérieur ?

async / await

5.6 course await

Re-écrivez le code dans <script> en utilisant await et sans utiliser .then()

Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:

async / await

5.7 Correction

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Course promesses</title>
<style>
#chat {
position: absolute;
left: 0px;
top: 0px;
width: 200px;
transition: left 1s,top 1s;
}
#souris {
position: absolute;
left: 400px;
top: 100px;
transition: left .5s,top .5s;
}
</style>
</head>
<body>
<img id="chat" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/chat.png"/>
<img id="souris" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/souris.svg"/>
<script src="https://moodle.iutv.univ-paris13.fr/img/bjs2/bjs2-js-lib.js"></script>
<script type="module">
const chat =document.getElementById('chat' );
const souris=document.getElementById('souris');
await attendre(1000);
chat.style.left='300px';
chat.style.top ='100px';
souris.style.left='400px';
souris.style.top ='300px';
await attendre(1000);
chat.style.left='250px';
chat.style.top ='200px';
souris.style.left='200px';
souris.style.top ='400px';
await attendre(1000);
chat.style.left='360px';
chat.style.top ='450px';
souris.style.left='500px';
souris.style.top ='600px';
</script>
</body>
</html>