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

Javascript Promises

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for sylzys sylzys
September 13, 2014

Javascript Promises

Entrez dans le monde des promesses Javascript - CaenJS V2

Avatar for sylzys

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