• Partagez
  • E-mail
  • Intégrer
  • J'aime
  • Télécharger
  • Contenu privé
Writing Asynchronous Javascript 101
 

Writing Asynchronous Javascript 101

on

  • 32,786 vues

A brief introduction to writing asynchronous javascript. A presentation from work.

A brief introduction to writing asynchronous javascript. A presentation from work.

Statistiques

Vues

Total des vues
32,786
Vues sur SlideShare
32,742
Vues externes
44

Actions

J'aime
19
Téléchargements
109
Commentaires
3

3 Ajouts 44

http://www.scoop.it 22
http://paper.li 21
http://a0.twimg.com 1

Accessibilité

Catégories

Détails de l'import

Uploaded via as Apple Keynote

Droits d'utilisation

© Tous droits réservés

Report content

Signalé comme inapproprié Signaler comme inapproprié
Signaler comme inapproprié

Indiquez la raison pour laquelle vous avez signalé cette présentation comme n'étant pas appropriée.

Annuler

13 sur 3 précédent suivant Publier un commentaire

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Votre message apparaîtra ici
    Processing...
Poster un commentaire
Modifier votre commentaire
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Writing Asynchronous Javascript 101 Writing Asynchronous Javascript 101 Presentation Transcript

  • WritingAsynchronousJavascript 101 Matt Perpickmatthewperpick@gmail.com 2011.10.14
  • Javascript 101
  • How does this work?function loadPage () { $(‘#spinner’).show(); setupPage(); $(‘#spinner’).hide();}
  • • A browser window has one thread that renders the DOM, dispatches events and executes Javascript.• This thread executes one code unit at a time.• Other code units are queued until the current code unit is finished executing.
  • It doesn’t.function loadPage () { // The DOM manipulation tasks // are not executed until this // task’s stack clears. The spinner // isn’t shown until setUp is // completed. $(‘#spinner’).show(); setupPage(); $(‘#spinner’).hide();}
  • Use an asynchronous task.function loadPage () { $(‘#spinner’).show(); // Queue a task to execute // when this stack clears. setTimeout(function () { setupPage(); $(‘#spinner’).hide(); }, 0);}
  • Javascript needs Async• Javascript is single threaded (mostly)• Long running tasks kill user experience• Long running tasks will timeout (especially on mobile browsers)• Thus, most I/O APIs are asynchronous • Ajax, WebSQL, IndexedDB, WebWorkers
  • Aside: Types of Javascript Tasks• Events• Timed scripts - setTimeout, setInterval• Callbacks - Ajax, WebSQL, WebWorkers, etc.• Script Tags• Javascript URLs• Others?
  • So how you do write asynchronous Javascript?
  • Callbacks!asyncStorage.get(key, function (val) { doSomething(val);}); • Javascript has no syntactic way of dealing with asynchronous code (unlike Erlang and co.) • We’re stuck with callbacks. • Callback programming can get complex.
  • Callback programming is hard.
  • Reason #1:Error Handling
  • How does this work?try { asyncStorage.get(key, function (val) { throw new Error(“argh”); });} catch (error) { alert(‘error!’);}
  • It doesn’t.• Tasks don’t share stacks.• Thus, errors in asynchronous callbacks won’t bubble up to callers.• Errors must be manually passed back to callers via callback functions.• There are two styles of doing this.
  • Different Styles// Have separate “onSuccess” and “onError”// callbacks. Used by WebSQLDatabase, jQuery, etc.var onSuccess = function (value) { doSomething(value); };var onFailure = function (error) { alert(‘aw shucks’); };asyncStorage.get(key, onSuccess, onFailure);// Use a single callback. If errors occur, they are// passed as the first argument to the callback. It// is up to the caller to check if the first argument// is non-null. This is a node.js convention and is// reminiscent of error checking in C.asyncStorage.get(key, function (error, value) { if (error) { alert(‘aw shucks error’); return; // Don’t forget this! } doSomething(value);});
  • In summary ...• Passing errors around via callbacks is a pain.• It requires much more discipline, more testing and some understanding of how the browser works.• Consistency is important. Choose one error passing style for your application.
  • Reason #2:Control Flow
  • Reason #2:Control Flow
  • Synchronous Flow is Easy/** * Show a list of songs for the artist with * the given name. */function showSongs (artistName) { var artist = artists.getByName(artistName); var albums = albums.getByArtist(artist); var songs = songs.getByAlbum(albums); songView.render(songs);}
  • Async flow is Spaghetti/** * Show a list of songs for the artist with * the given name and execute the callback when * complete. */function showSongs (artistName, callback) { // And we’re not even handling errors! artists.getByName(name, function (artist) { albums.getByArtist(artist, function (albums) { songs.getByAlbum(albums, function (songs) { songView.render(songs); return callback(); }); }); });}
  • Control Flow Code Helps• Avoid a filthy rat’s nest of callbacks.• Keep your tasks disjoint from your control flow.• Control flow is readable in one place.
  • Control Flow Libraries• async.js - https://github.com/caolan/async • async functional utilites + control flow• do.js - https://github.com/creationix/do • control flow via continuables• jquery.deferred.js - http://jquery.com • promises• language extentions options, others
  • Let’s check out async.js• One of many means of doing control flow.• asynchronous functional utilities • e.g. each, map• async control flow • e.g. series, parallel, waterfall
  • Examplefunction showSongs (artistName, callback) { var renderTask = function (songs, renderCallback) { try { songView.render(songs); return renderCallback(null); // No errors! } catch (error) { return renderCallback(error); } }; // The control flow is encapsulated in one place // in clear, concise, readable manner. var tasks = [ async.apply(artists.getByName, artistName), async.apply(albums.getByArtist), async.apply(songs.getByAlbum), async.apply(renderTask) ]; async.waterfall(tasks, callback);}
  • In summary• Callbacks don’t scale.• You need to build scaffolding to manage the complexity.• Separate your control flow from your tasks.
  • Reason #3:Debugging
  • Ease the pain (a little)• Add module or class names to console log messages to easily trace the flow.• Breakpoints everywhere!• This still sucks.
  • Conclusion• Writing asynchronous Javascript is hard.• Complexity can spiral out of control.• Plan for it.• Beware.• Good luck.
  • Fin.Questions? Comments?
  • Further reading• http://dev.opera.com/articles/view/timing-and- synchronization-in-javascript/• http://ejohn.org/blog/how-javascript-timers-work/• http://www.whatwg.org/specs/web-apps/current- work/multipage/webappapis.html#event-loops