Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Javascript Promises

sylzys
September 13, 2014

Javascript Promises

Entrez dans le monde des promesses Javascript - CaenJS V2

sylzys

September 13, 2014
Tweet

More Decks by sylzys

Other Decks in Technology

Transcript

  1. synchrone Javascript (y compris V8) est mono-thread. ! function getUser(name)

    { var sql = 'SELECT * FROM users WHERE name=?'; var user = query(sql, name); //<-- bloquant if (! user) throw new Error ('no user!' ); return user; }
  2. asynchrone function getUser (name, callback) { var sql = 'SELECT

    * FROM users WHERE name=?'; query(sql, name, function (error, user ) { if (error) { callback(error); } else if (!user) { callback(new Error ('no user!' )); } else { callback(null , user); } }); }
  3. callbacks Fonction passée en paramètre à une autre fonction, et

    exécutée au sein de celle-ci. ! var talk = document.getElementById("talk"); talk.addEventListener("click", function(event){ alert("You chose a talk"); }); ! $('#talk').click(function(event) { alert("You chose a talk"); });
  4. callbackS fs.readFile('/etc/passwd', function (err, data) { if (err) throw err;

    console.log(data); }); function mainCode(callback){ doSomething(); callback(); } ! function myCallback(){ console.log("This is my callback"); } ! mainCode(myCallback);
  5. callback hell getEvent("CaenJS", function (error, _event){ if (error) { manageError(error);

    } else { getTalks(_event, function(error, talks){ if (error) { manageError(error); } else { getSpeakerDetails(talks[0].id, function(error, details){ if (error) { manageError(error); } else { displayInUI(details); } }); } }); } });
  6. callback hell fs.readdir(source, function(err, files) { if (err) { console.log('Error

    finding files: ' + err) } else { files.forEach(function(filename, fileIndex) { console.log(filename) gm(source + filename).size(function(err, values) { if (err) { console.log('Error identifying file size: ' + err) } else { console.log(filename + ' : ' + values) aspect = (values.width / values.height) widths.forEach(function(width, widthIndex) { height = Math.round(width / aspect) console.log('resizing ' + filename + 'to ' + height + 'x' + height) this.resize(width, height).write(destination + 'w' + width + '_' + filename, function(err) { if (err) console.log('Error writing file: ' + err) }) }.bind(this)) } }) }) } }) http://callbackhell.com/
  7. callbackS Return / Throw function getUser (name, callback) { var

    sql = 'SELECT * FROM users WHERE name=?'; query(sql, name, function (error, user ) { //personne ne récupère cette valeur return user; }); } function getUser (name, callback) { var sql = 'SELECT * FROM users WHERE name=?'; query(sql, name, function (error, user ) { //personne ne catch l'exception if(error) throw error; }); }
  8. callbackS • Lisibilité (nesting) • Complexité du code • Maintenabilité

    • Pas de garantie d’exécution • Return ? Throw ? • Simplicité • Poids réduit
  9. promises • Prémices aux alentours de 1989 • Principe actuel

    inspiré du langage E (Mark Miller) • Principe bcp utilisé en dehors du JS • 1re version des specs par le groupe CommonJS • Spéc actuelle Promises/A+ • Ember, Angular, Dojo, etc.
  10. promises Représente le résultat d’une opération asynchrone. Objet 1re classe,

    qui aura, à un moment, une valeur. 3 états possibles : • Pending • Fulfilled (renvoie une valeur) • Rejected (renvoie une raison) ! Permet de retrouver les bénéfices du synchrone : return, throw, catch, re-throw
  11. promises • Rendre disponibles en « asynchrone » les opérations

    existantes en « synchrone » : • return / throw / catch / rethrow ! • Bénéficier d’un callstack en mode asynchrone Pourquoi
  12. promises • Requête(s) AJAX (simple, chainées..) • Chargement asynchrone d’asset

    avec actions à réaliser • Animation • … Cas d’utilisation
  13. promises Garanties promiseForResult.then(onFulfilled, onRejected); ! onFulfilled OU onRejected sera appelée,

    une seule fois. ! onFulfilled sera appelée avec une valeur (return) onRejected sera appelée avec une raison du rejet (thrown exception)
  14. promises Chaînage var transformedPromise = originalPromise.then(onFulfilled, onRejected); ! Si le

    handler appelé renvoie : ! • une valeur : transformedPromise passera à l’état « resolved » avec cette valeur ! • une promise : transformedPromise adopte son état ! Si le handler appelé renvoie une exception, transformedPromise passera en « rejected » avec l’exception renvoyée. !
  15. promises Création var promise = new Promise(function(resolve, reject) { //

    do something ! if (/* everything is OK */) { resolve("Good !"); } else { reject(Error("UhOh...")); } }); promise.then(function(result) { console.log(result); // "Good !" }, function(err) { console.log(err); // Error: "UhOh..."" });
  16. promises step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) {

    step4(value3, function(value4) { // Do something with value4 }); }); ! }); }); ! ! Q.fcall(promisedStep1) .then(promisedStep2) .then(promisedStep3) .then(promisedStep4) .then(function (value4) { // Do something with value4 }).done(); Callback Hell ?
  17. promises Exceptions ! try { var v1 = step1('foo'); var

    v2 = step2(v1); var v3 = step3(v2); var v4 = step4(v3); } catch (error) { handleError(error); } Synchrone Callbacks var handleError = console.log; ! step1('foo', function (error, v1) { if (error){ handleError(error); } else { step2(v1, function (error, v2){ if (error){ handleError(error); } //[…] else { //do something with v4 } }); } }); } }); } });
  18. promises Exceptions promisedStep1('foo') .then(promisedStep2) .then(promisedStep3) .then(promisedStep4) .then(function (value4) { //

    Do something with value4 }) .then(undefined, handleError); Promises ! try { var v1 = step1('foo'); var v2 = step2(v1); var v3 = step3(v2); var v4 = step4(v3); } catch (error) { handleError(error); } Synchrone
  19. promises • (Encore) peu d’implémentation natives • Certaines librairies non

    conformes aux specs • CallStack • Garanties • Return / Throw • Catch / Rethrow
  20. Librairies https://github.com/kriskowal/q ! Permet également d’utiliser des Promises en remote

    var Q = require("q"); var Connection = require("q-comm"); var remote = Connection(port, local); // a promise for a remote object! var userPromise = remote.getUser(); twitter.com/domenic Q.js
  21. Et maintenant • Les Promises sont intégrées à ES6 •

    Les API DOM les utiliseront aussi • Large utilisation dans Angular (templates, etc.) • Utilisation dans Ember, Dojo…
  22. vanilla Certaines APIs DOM ayant des succès/échecs asynchrones utilisent les

    Promises (gestion de quota, événements de chargement de pontes, ServiceWorker, .… ! Implémentation native partielle dans certains navigateurs. ! Chrome : promesses activées par défaut dans Canary. Firefox : la dernière nightly, intègre les promesses. ! Pas encore d’implémentation complète ou conforme à 100% !
  23. BONUS La plupart des librairies offre des fonctions / patterns

    utiles ui.startSpinner(); getUser("Domenic") .then(getBestFriend) .then(ui.showBestFriend) .catch(ui.error) .finally(ui.stopSpinner) .done(); twitter.com/domenic All, spread, map, invoke, denodeify …
  24. toolbox • https://www.youtube.com/watch?v=hf1T_AONQJU • http://promisesaplus.com/implementations • http://www.html5rocks.com/fr/tutorials/es6/promises/ • http://domenic.me/2012/10/14/youre-missing-the-point- of-promises/

    • http://fr.slideshare.net/domenicdenicola/promises- promises • http://fr.slideshare.net/domenicdenicola/callbacks- promises-and-coroutines-oh-my-the-evolution-of- asynchronicity-in-javascript • http://blog.carbonfive.com/2013/10/27/the-javascript- event-loop-explained/
  25. CREDITS • Images : • Balakov - https://www.flickr.com/photos/balakov • Fonts

    : • Roboto - By Dharma Type // Dharma Type Font License v1.00 • Bebas Neue - By Christian Robertson // Apache License v2.00