Avec corrigé

Promise et fonctions async

Technologie web 3

Johan Girod

Rappel : code asynchrone = callback


        

Problème : callback hell


        

Les Promise (promesses) permettent de résoudre ce problème.

Utiliser une Promise

Une promesse est un objet avec une méthode then qui prend un callback appelé une fois : quand la promesse est résolue.


        

Enchainer les Promise

Si on retourne une promesse dans un .then(), on peut enchainer les promesses.


        

Créer une Promise

On utilise new Promise, un constructeur qui accepte une fonction avec un argument resolve


        
        

Les promesses peuvent retourner des valeurs

On peut voir les promesse comme des boites qui contiennent une valeur qui existera dans le futur.


        
        

Combiner les promesses - Promise.all


        
        

Les promesses sont exécutées en parallèle, puis le .then() est appelé une fois que toutes les promesses sont résolues.

Combiner les promesses - Promise.race


        
        

Le .then() est appelé dès que la première promesse est résolue.

async / await

Quand une fonction manipule des promesses, on peut utiliser async et await pour rendre le code plus lisible.


        

Les fonctions async retournent une promesse, qui est résolue avec la valeur retournée.


        
	

A savoir

  • On peut utiliser await pour attendre n'importe quelle promesse
  • Pour utiliser await, la fonction doit être déclarée avec async.
  • On peut utiliser await dans une boucle ou dans une condition

À vous de jouer !

TP Memory (suite)

On continue le jeu de memory en ajoutant des fonctionnalités asynchrones.

  1. Créer une fonction asynchrone boucleJeu. La fonction doit :

    • attendre que l’utilisateur clique sur une carte
    • retourner la carte cliquée
    • répéter ces étapes jusqu’à ce que toutes les cartes soient retournées.

    On pourra utiliser la fonction suivante :

    /**
     * Renvoie une `Promise` qui `resolve` quand une carte a été cliquée. Le contenu de la Promise est l'index de cette carte dans le tableau.
     */
    type CardIndex = number;
    async function clickOnCard(): Promise<CardIndex> {
    	return new Promise((resolve) => {
    		const listener = (event: MouseEvent) => {
    			console.log(event.target);
    			if (!event.target.classList.contains('carte')) {
    				return;
    			}
    			const index = Array.from(event.target.parentNode.children).indexOf(
    				event.target as HTMLElement
    			);
    			resolve(index);
    			document.removeEventListener('click', listener);
    		};
    		document.addEventListener('click', listener);
    	});
    }

    Cette fonction retourne une promesse resolvant sur la l’index de la carte cliqué. On peut donc l’utiliser dans une fonction asynchrone pour attendre que l’utilisateur clique sur une carte.

    async function boucleJeu() {
    	// à compléter ...
    	const index = await clickOnCard();
    	console.log(`Carte cliquée : ${index}`);
    	// à compléter ...
    }
    boucleJeu();
    Corrigé
  2. Modifier la fonction ci-dessus pour ajouter le comportement suivant :

    Si deux cartes sont retournées, les cacher après une seconde si elles ne sont pas identiques.

    Corrigé
  3. Créer une fonction principale asynchrone main. Le jeu se termine si toutes les cartes sont retournées en moins de 30 secondes, ou si le joueur a gagné. Lorsque le jeu se termine :

    • retourner face visible toutes les cartes restantes
    • afficher un message de félicitations si le joueur a gagné, ou un message d’encouragement sinon.
    • afficher un bouton pour rejouer.

    On pourra utiliser Promise.race.

    Corrigé
  4. Faire en sorte d’afficher le nombre de secondes restantes avant la fin du jeu.