2. What is Synchronicity?
• Understanding asynchronous programming is only possible, if you have
an idea about basic principles.
• Threading is one of them. We are humans and multi-threading is how our brain
works. We can drive a car, while answering a phone call and we are also able to
digest our food and smell the farts of our fellow passengers.
• But we can‘t do any tasks arbitrarely in parallel. There are limits. We can‘t talk
about sex, think about quantum physics and try to remember when our next
meeting is scheduled. Tasks start blocking each other. Some are non-blocking and
others block our ability to do multi-tasking.
• Sneezing for example is blocking. Every action stops, while we are sneezing. Thus
making sneezing a synchronous action. Except for our heart beat, which is never
blocked by other processes
• Ok, so it looks like we always want to have non-blocking processes, but it is not
that easy!
3. Is Javasript asynchron?
• No!
• Javascript is synchron and even worse single-threaded. To be
correct, JS is interpreted synchronous and the interpreters run
single-threaded.
• Single-threaded means only one command at a times is processed. So you
might ask, why the hell does anyone want to code asynchronous in
Javascript?
• The answer is very simple: Because we want to.
• This is because we want to click a button on our page and have it load
some other stuff, while the rest of the page is still accessible. We want to
show already loaded parts of the gallery and don’t want to wait until
everything is downloaded and then start showing off all content.
4. Visualisation of synchronicity
• Simple example: reading a book!
• Synchronous…
Open chapter Loading Read chapter Next chapter Loading Read chapter
5. Visualisation of synchronicity
• In contrast: reading a book asynchronous!
Loading #1
Chapter 1
Loading #2
Chapter 2
Loading #3
Chapter 3
6. How can JS be asynchronous?
• Well even though JS is synchronous single-threaded, we can start
asynchronous tasks with one command at a time. Imagine a king,
who sends out his knights and servants to do certain things.
• The king has no idea what one knight is doing at the moment. But he has
given instructions. And the knight has to come back and give a report to
the king. This makes it possible for him to do many things parallel through
his servants.
• While a servant is on his way doing something, the king cannot contact
him. He cannot stop him from accomplishing his orders. And furthermore
he doesn’t know if his knights get killed on the mission or desert.
Remember: Back in these days mobile phones did not exist!
7. Knights and Kings
• You might say we live in the age of mobile communication and the
knights should have mobile phones with them. The answer is yes,
there are some parallel programming paradigms which can do that,
for example Open MPI. In this country the king has a leash and can
always control his servants.
• In computers this is called threads with process IDs. You can send
messages to threads and control them, kill them, spawn more and
have them waiting for work and so on. But this is the country of
Java and C++. In the mighty realm of Javascript we don’t want to
control our Knights tightly, because everything should run smooth
and fast.
8. Basic examples
• Before we get totally lost in the middle ages, let’s have an example:
var fs = require('fs');
var content = fs.readFileSync('index.html');
console.log(contents);
Well, the content is loaded and then displayed in the console.
But while it is being loaded, nothing else will happen. If our hard
disk is much slower than our CPU, we could do other things in
between. And no surprise, this is near to always the case.
9. Async File Read
• Then let’s have an alternative example:
var fs = require('fs');
fs.readFile('index.html', function(err, contents){
console.log(contents);
});
var fs = require('fs'); fs.readFile('index.html', function(err, contents){ console.log(contents); });
Remember anonymous functions?
Here is one, let‘s name it a callback.
10. Callbacks
var fs = require('fs');
var callback = function(err, contents){ console.log(contents); }
fs.readFile('index.html', callback);
• We could have done it this way as well. The function acts the same
but it is no longer anonymous.
• So what are callbacks? Well, this is the order the knights get from
the king, what they have to do after finishing or how to report back
at a certain stage.
11. Async File Read
var http = require('http');
var fs = require('fs');
http.createServer(function(request, response) {
response.writeHead(200);
fs.readFile('index.html', function(err, contents) {
response.write(contents);
response.end();
});
}).listen(8080);
Callback #1
Callback #2
This might look magical at first glance. Keep in mind
that functions are objects as well. Here an object is
created which handles a request and a response.
The first callback is called when createServer is
finished and the second after the readFile is finished.
12. In royal terms
• The king says: “My loyal first knight, go forth and create server!”
http.createServer(…)
• He continues: “Afterwards, write head and read the file index.html!”
function(request, response) {
response.writeHead(200);
fs.readFile('index.html',…)
• The knight accepts this order, but he thinks “file read is no fun, let my page do that for me!”
function(err, contents) { response.write(contents); response.end(); });
• Furthermore he says his page: “After you have done that, put the content into this response
letter and I will bring it to the king!”
13. async.each
var async = require('async');
var gather_troops = function(num, Callback) {
console.log('squad '+num+' reporting in!');
return Callback(null);
};
async.each([1, 2, 3, 4], gather_troops, function (err) {
console.log("Army ready!");
});
The package
async is required
The king wants to
gather troops!
The king gives out
orders through
async.each
14. Building an asynchronous army!
async.each([1, 2, 3, 4], gather_troops, function (err) {
console.log("Army ready!"); });
• The function async.each will
run the function
gather_troops with each
entry in the given array
[1,2,3,4] and afterwards write
a report to the console.
squad 1 reporting in!
squad 2 reporting in!
squad 3 reporting in!
squad 4 reporting in!
Army ready!
15. async.map
var make_delicious_course = function (num, Callback) {
return Callback(null, num+'. course');
};
async.map([1, 2, 3, 4], make_delicious_course, function (err,
results) {
console.log(results);
console.log("Lordes, disheth ready!");
});
map instead of each! The callback carries a string now!
The results are
printed here and not
in the called function!
16. map vs each
• Why is the king very careful that in the last example map is used
instead of each?
• Because each does not return an array. When the army is gathered, he only
wants to hear from them, that they are ready. But when food is cooked,
returning the courses is very important.
• Map does return an array. Therefore the king can eat the food, because he
has the food at hand.
• So if just want to execute some things parallel, just use each. But if
you need something back, map will be the better option. Speaking
in websites, in one case you want to display some <divs> in
another case you need reference to some spawned buttons, too.
17. Races
• To be honest, the cooks need different amount of time for preparing the
courses.
var make_delicious_course = function (num, Callback) {
setTimeout(function() {
console.log("dish #"+num+" is being prepared!");
return Callback(null, num+'. course');
}, 100 * Math.random());
};
• What does that mean? Well we have just added a timeout that waits until some
time is over and then proceeds. Thus simulating different amounts of time the
cooks will need.
setTimeout takes an
anonymous callback
function as argument!
18. Races
• Ok, let’s try it out!
async.map([1, 2, 3, 4], make_delicious_course, function (err, results) {
console.log(results); console.log("Lordes, disheth ready!");
});
dish #2 is being prepared!
dish #1 is being prepared!
dish #3 is being prepared!
dish #4 is being prepared!
[ '1. course', '2. course', '3.
course', '4. course' ]
Lordes, disheth ready!
This may be surprising. We see that our
asynchronous tasks run in an arbitrary order.
That is not too surprising, since we understand
what asynchrony means. But still the array is in
the right order. This is because the async.js
library takes care of the order in this case. If we
had build a function “map” by ourselves, we
would have to remember the running order
and sort the array in the end.
19. Races
• Races occur everywhere in asynchronous code. But if code is
designed carefully they are never a problem at all.
• The whole design how asynchronous programming is done in
Javascript prevents critical implications of races very well. This is
because you don’t know what your knights are doing. And they
don’t know what other knights are doing. Therefore critical data
races occur especially when handling global variables.
• But we all know global variables are bad style. In parallel
programming this is even more the case.
• Debugging races can be painful – even for kings.
20. Convention
• Let’s take a look at a callback function:
function (err, results) {
console.log(results);
console.log("Lordes, disheth ready!");
}
• Maybe you have noticed that all take arguments in the order “error” and then
“something” to proceed with. In this case these arguments were “err” and
“results”. There is a convention in the community of JS to put error handling
first and the rest afterwards. Most libraries stick to this behavior and it is
advisable to stick to it as well. If you don’t want to handle errors, because you
are the king or so, then you can still pass “null”:
return Callback(null, num+'. course');
21. Christmas Trees
• Christmas trees are nice, because there are a lot of surprises below. In Javascript it is the same, that is why
Josh Wright has coined this name in his tutorial. How does a Christmas tree look like?
asyncFunc1(function(err, result) {
asyncFunc2(function(err, result) {
asyncFunc3(function(err, result) {
asyncFunc4(function(err, result) {
asyncFunc5(function(err, result) {
// It's Christmas! Praise the lord etc.
}
}
}
}
}
22. Christmas Trees
• So basically this just means that each async call leads to the source
code being indented and you lose overview really fast.
• Others name this effect “callback hell”
• Furthermore we haven’t seen error handling yet. This adds in to the
topic “our code gets swollen up”
• In the final part of this introduction to asynchronous programming
in Javascript, we will see at least one way to trim code and make it
look more like synchronous code.
• So let’s have a look at promises!
23. Registration – classic callbacks
this.register = function (email, callback) {
_save(email, function (err) {
if (err)
return callback(err);
_send(email, function (err) {
callback(err);
});
});
};
};
var Registration = function () {
var _save = function (email, callback) {
setTimeout(function(){
callback(null);
}, 20);
};
var _send = function (email, callback) {
setTimeout(function(){
callback(new Error("Failed to send"));
}, 20);
};
Yay! Christmas Tree!
24. Classic callbacks in action
• We have a class “Registration”, which allows us to register, send and save
users. All functions are just dummies to show how error handling works.
We use it with the following code:
var registry = new Registration();
registry.register("john@example.com", function (err) {
console.log("done", err);
});
• The output tells us that the built-in error occurred and was printed
successfully. Now let’s do the same with promises…
done [Error: Failed to send]
25. Promises
• Also called Futures. But for node.js promise is the common name.
• A promise can have different states:
• fulfilled
• rejected
• pending
• (settled)
• If your function is used as a promise, you can say what happens
when the promise has fulfilled or rejected. Or more precise, what
happens “then”.
26. Promises
var deferred = require('deferred');
var Registration = function () {
var _save = deferred.promisify(function (email, callback) { callback(null); });
var _send = deferred.promisify(function (email, callback) { callback(new Error("Failed
to send"));
});
this.register = function (email, callback) {
//chain two promises together and return a promise
return _save(email).then(_send);
};
};
The function is
promisified
Therefore it becomes
„thenable“
27. Promises in action
var registry = new Registration();
registry.register("john@example.com")
.then(
function () {
console.log("Success!");
},
function (err) {
console.log("Failed with error:", err);
}
);
Failed with error [Error:
Failed to send]
28. Promises
• Promises let your asynchronous code look more usual. No
Christmas tree effect, no callback hell.
• Furthermore you can collect all errors in nested functions, which call
each other with then. Then you can throw all errors at once.
• Promises standardize the way asynchronous code is managed.
Functions you run have a precise state of either pending or settled.
When settled you know if they fulfilled or failed (rejected).
• Promises are not a must have, but they give the feeling of returning
code back.
29. Further read and sources
• http://javascriptplayground.com/blog/2013/06/think-async/
• http://www.joshwright.com/tips/javascript-christmas-trees-
promises-and-event-emitters
• http://www.html5rocks.com/en/tutorials/es6/promises/