Click here to load reader
Upload
hackbulgaria
View
426
Download
0
Embed Size (px)
DESCRIPTION
This is presentation from Nemetschek Bulgaria - one of the partners of HackBulgaria's JavaScript course. The topic is Async JS -How does the event loop in JS works and what are the benefits of the Promises.
Citation preview
Async JavaScript & Promises/A+Martin Dimitrov
July 2014
About meMartin Dimitrov
[email protected] Developer Web Technologies, Nemetschek Bulgaria
JavaScript
● The single language available in Modern Web Browsers.● Full stack Web programming with Node.js● Single-threaded & Event-driven asynchronous processing● Jeff Atwood Atwood’s law:
“Any application that can be written in JavaScript will eventually be written in JavaScript.”
Functions & Callbacks
● Functions are first class citizens in JavaScript● Functions can accept other functions as parameters and call
them either synchronously or asynchronously.
Callbacks example
$('#saveButton').on('click', function(){ $(this).closest('form').submit();});
function readJSON(filename, callback) { fs.readFile(filename, 'utf8', function(err, res) { if (err) return callback(err); try { res = JSON.parse(res); } catch (ex) { return callback(ex); } callback(null, res); });} Pyramid of Doom
step1(function(result1) { step2(function(result2) { step3(function(result3) { // and so on... }); });});
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)) } }) }) }});
Example 1http://codepen.io/sachmata/pen/Hoygz/
for (var i = 1; i <= 3; i++) { setTimeout(function() { console.log('async: ' + i); }, 0); console.log('sync: ' + i);}
Example 2http://codepen.io/sachmata/pen/GrmFE
var start = Date.now();setTimeout(function() { var end = Date.now(); console.log('Time elapsed:', end - start, 'ms');}, 500);
while (Date.now() - start < 1000) { // do nothing};
Types of Async Functions
● I/O Functions (XMLHttpRequest)● Timing Functions (setTimeout, setInterval, setImmediate,
requestAnimationFrame)● Sometimes-Async Functions (caching)
Error handling in Async Functions
● throw from callback● try/catch over async function does not work !
setTimeout(function A() { setTimeout(function B() { setTimeout(function C() { throw new Error( 'Something terrible has happened!'); }, 0); }, 0);}, 0);
Error: Something terrible has happened!at Timer.C (/AsyncJS/nestedErrors.js:4:13)
try { setTimeout(function() { throw new Error( 'Catch me if you can!'); }, 0);} catch (e) { console.error(e);}
What is a promise? http://www.promisejs.org/
The core idea behind promises is that a promise represents the result of an asynchronous operation. A promise is in one of three different states:
● pending - The initial state of a promise.● fulfilled - The state of a promise representing a successful operation.● rejected - The state of a promise representing a failed operation.
Once a promise is fulfilled or rejected, it is immutable (i.e. it can never change again).
Specification Promises/A+ http://promisesaplus.com/ - (thenable) defines only 'then' method
promise.then(function(result) { console.log(result); // "Stuff worked!"}, function(err) { console.log(err); // Error: "It broke"});
Browser support● Q● when● WinJS● RSVP.JS● jQuery 1.8+ (Deferred object) ! Not Promise/A+ compliant !● Conformant Implementations of Promises/A+ / Test suite
https://github.com/promises-aplus/promises-spec/blob/master/implementations.md● ECMAScript 6
jQuery Example (probably you have already used promises - new ajax module)
// Assign handlers immediately after making the request,// and remember the jqxhr object for this requestvar jqxhr = $.get("example.php", function() { console.log("success");}).done(function() { console.log("second success");}).fail(function() { console.log("error");}).always(function() { console.log("finished");});
// Perform other work here ...
// Set another completion function for the request abovejqxhr.always(function() { console.log("second finished");});
Creating jQuery promiseOption 1function readJSON(filename) { var task = $.Deferred(); fs.readFile(filename, 'utf8', function(err, res) { if (err) return task.reject(err); try { res = JSON.parse(res); } catch (ex) { task.reject(err); } task.resolve(res); }); return task.promise();}
Option 2function readJSON(filename) { return $.Deferred(function(task) { fs.readFile(filename, 'utf8', function(err, res) { if (err) return task.reject(err); try { res = JSON.parse(res); } catch (ex) { task.reject(err); } task.resolve(res); }); }).promise();}
Other Deferreds in jQuery API
Animationsvar dialogPromise = $('#dialog').fadeIn().promise();dialogPromise.done(afterDialogShown);
Document ready$(onReady);$(document).ready(onReady);$.ready.promise().done(onReady);
What we get from promises?
● Invocation chaining/combining● Error propagation● Common error handling● Common success handling● Progress notification (if supported)● Wrap other async solutions
You're Missing the Point of Promises !http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/
Chaining Promises
getJSON("/posts.json").then(function(json) { return json.post;}).then(function(post) { // proceed});
ErrorsgetJSON("/posts.json").then(function(posts) { // }).catch(function(error) { // since no rejection handler was passed to the // first `.then`, the error propagates.});
getJSON("/post/1.json").then(function(post) { return getJSON(post.commentURL);}).then(function(comments) { // proceed with access to posts and comments}).catch(function(error) { // handle errors in either of the two requests});
Promise with Exception
var userPromise = getUser().then(function(user) { if (user === null) { throw new Error('user is null'); } return user;}).then(function(user){...}, function(err){...}).done();
Beware of unhandled exceptions/rejections when no reject callback is registered! Unhandled Exceptions in synchronous code will hit the top of the stack, here might sink silently. Use 'done' method at the end of Promises chain to signal that any unhandled exceptions should explode.
try/catch/finally
startSpinner();getUser('martin') .then(getProfile) .then(showProfile) //.then(errorThrowingFunction) .catch(displayError) .finally(stopSpinner) .done();
Q.all / RSVP.all / $.when / WinJS.Promise
var promise = Q.all([getUser(), getCompany()]).then(function(results) {…});var promise = $.when(getUser(), getCompany()).then(function(user, company) {…})
var promise = WinJS.Promise.join({ user: getUser(), company: getCompany()}).then(function(data) {…}).done();
var promise = WinJS.Promise.any([ getUser(), getCompany()]).then(function(winner) {…}).done();
Theoreticaly Promises/A+ compliant promises from different implementations can be mixed, but jQuery promises are not compliant – assimilate as soon as possible.
var realPromise = when(jQueryPromise);
Promises/A+ Performance Hits You Should Be Aware Ofhttp://thanpol.as/javascript/promises-a-performance-hits-you-should-be-aware-of/
Recommended reads
Async JavaScript: Build More Responsive Apps with Less Codeby Trevor Burnham
JavaScript: The Good Partsby Douglas Crockford
Thank you. Questions?