Cet article est la suite d’une série d’articles sur ES6 :
- quelques nouveautés de la prochaine version de JavaScript.
- quelques nouveautés de la prochaine version de JavaScript – Part II
Avant de commencer, une petite information en terme de nommage, ES6 a été renommé en ES2015.
Promise
Définissons tout d’abord ce qu’est une promesse :
Une promesse représente l’éventuel résultat d’une opération asynchrone
La notion de promise (promesse en français) n’est pas nouvelle et existe dans différentes librairies sous différentes formes comme :
- $q dans angular, inspirée par librairie Q
- BlueBird.js
- deferred en jquery
Les Promise seront inclus de manière native dans ES6.
Les promise permettent de gérer plus facilement les méthodes asynchrones et d’éviter un code difficile à lire et maintenable si on utilise des callback. En effet on arrive facilement à avoir du code comme cela :
step1(function (value1) { step2(function (value2) { step3(function (value3) { step4(function (value4) { step5(function (value5) { step6(function (value6) { // Do something with value6 }); }); }); }); }); });
C’est ce qu’on appelle pyramid of doom ou callback hell.
Un nouvel objet Promise est introduit dans ES6. Le constructeur prend en paramètre une fonction avec 2 fonctions en paramètre : resolved et reject. La fonction resolve est à appeler si il n’y a pas eu d’erreur avec les valeurs de retour. Elle permet d’indiquer que la promise est résolue permettant la suite des actions. La fonction reject est à appeler si une erreur est survenue.
Création d’une Promise
var promise = new Promise( function (resolve, reject) { // (A) ... if (...) { resolve(value); // success } else { reject(reason); // failure } });
Une fois notre promise définie, nous allons pouvoir définir un handler sur cette promise afin de réaliser des actions sur la future valeur. L’enchaînement des actions se fait via la méthode then. Cette fonction prend en paramètre 2 fonctions: la 1ere pour le succès (resolve) et la deuxième lors d’une erreur (reject). Les erreurs peuvent être également gérés via la méthode catch.
Utilisation d’une promise
httpGet('http://myServer.com/file.txt') .then( function (value) { //Success console.log('Contents: ' + value); }, function (reason) { //Error console.error('An error occurred', reason); });
L’avantage des promises est qu’on peut facilement les chaîner, ou les composer.
Fetch, la nouvelle API pour faire des appels Ajax utilise les promises. (un article pour aller plus loin)
Il existe des polyfills afin de pouvoir les utiliser dès maintenant :
Quelques liens sur le sujet :
- Embracing Promises in JavaScript
- Un article sur les promise sur html5rocks
- Fondamentaux et API des promises.
- La specs des promises/a+
- les promesses enjavascript/
- un screencast (utilisation de q) sur tagtree.io
Destructuring
Le destructuring permet d’initialiser des variables en les extrayant à partir d’objet existant.
//Array : on extrait 3 variables m, d et y à partir d'un tableau var [m, d, y] = [12, 21, 1981]; //object : on extrait les propriétés d'un objet //Ici on définit une fonction qui extrait la liste des classe CSS d'un élément var listOfCLass = function ({ classList } ) { Array.from(classList).forEach( (item) => console.log(item)) }; listOfCLass(document.body);
Une autre utilisation avec un module quand on ne veut importer qu’une partie d’un module. (cf chapitre module dans la partie II).
Quelques liens :
- ECMAScript 6 and Destructuring Assignment
- ES6 Destructuring sur javascriptplayground.com
- ES6 Destructuring sur medium.com
ES7
La future version d’EcmaScript est déjà en préparation et je vais parler de 2 des nouveautés qui sont à mes yeux les plus intéressantes.
Object.observe
Object.observe() est une nouvelle API qui permet de s’abonner aux changements effectués sur un objet. A chaque modification sur l’objet, un événement sera lancé contenant la liste des changements (ajout d’une propriété, modification d’une valeur, suppression d’une propriété) sur l’objet.
Voici un exemple tirée de la documentation de Object.observe sur MDN :
var obj = { foo: 0, bar: 1 }; Object.observe(obj, function(changes) { console.log(changes); }); obj.baz = 2; // [{name: 'baz', object: <obj>, type: 'add'}] obj.foo = 'hello'; // [{name: 'foo', object: <obj>, type: 'update', oldValue: 0}] delete obj.baz; // [{name: 'baz', object: <obj>, type: 'delete', oldValue: 2}]
Cela permet notamment de facilement mettre en place du data-binding (Angular 2 l’utilise afin d’améliorer les performances et éviter le « dirty checking »).
Quelques liens sur le sujet :
Async/Await
ES6 simplifie, via l’introduction des promesses, grandement la gestion de code asynchrone. Async va encore plus loin afin de faciliter la lecture et la compréhension.
ES7 introduit 2 nouveaux mots clés : async et await.
async permet de définir une fonction comme étant asynchrone alors que await permet d’indiquer que l’on souhaite bloquer l’exécution du code jusqu’au retour de la fonction.
Voici un exemple d’utilisation :
async function getUserName() { return 'royto'; } async function displayLogoutMessage() { var user = await getUserName(); alert(`GoodBye ${user} !`); }
Pour ceux qui viennent du monde .NET cette syntaxe ne devrait pas les surprendre 🙂
Quelques liens :
Liens sur ES6 / ES2015
- Des exemples de features apportés par ES6 et leur équivalent en ES5
- une série d’article ES6 sur hacks.mozilla.org
- Mosaic : une séries d’exercice pour apprendre JS et ES6
- À la découverte de ES2015 : partie 1 et partie 2
- Count to 6< : un workshop sur ES6 basé pour Node/li>
- ES6 Uncensored : une présentation sur ES6
- Expert ES6 sur tagtree : des exercices pour apprendre ES6
- 4 screencast sur ES6 sur tagtree.io : épisode 1, épisode 2, épisode 3 et épisode 4
- Un PDF sur les nouveautés ES2015 par Xebia