1. Topic: Asynchronous Programming

1.1. Introduction

Coverage of the upcoming module

During this module we will explore the first part of aynchronous programming using Generators. Since it shows how simple it will be in the end. Than we dive into asynchronous programming using callbacks, then we dive into Promises which are even better than callbacks but also make a mess of code sometimes, and finally we will end using the async await principle and in the end we will review the principle of generator(s) again to see what we saw in the start is more than we saw in the start of this module :-)

Synchronous vs Asynchronous

Without knowing it you use a lot of synchronous and asynchronous action during the day.

Simply said, an action is synchronous when you are waiting for a response or a result

Examples of synchronous daily actions
  • talking face-to-face to a person

  • making a phone call

  • sitting in a meeting

Examples of asynchronous actions
  • using email

  • using whatsapp

  • using facebook

  • sending a snail-mail letter

  • …​

This kind of actions are also applicable for programming related actions which will be the subject of this module

Introduction using the generator to begin with

Imagine the Ferrari factory; do you think that they make a dozen of Ferrari’s without orders? No …​ they make Ferrari’s when someone has bought one so they have the so-called pull strategy which of course is handy to prevent spending money on never bought cars

That principle is applicable with JavaScript as well using Generators

Generators

The ability of functions to be paused and then resumed again is not exclusive to async functions. JavaScript also has a feature called generator functions. These are similar, but without the promises.

When you define a function with function* (placing an asterisk after the word function), it becomes a generator. When you call a generator, it returns an iterator so we can iterate / loop over it!

A simple example (printing 3, 9 and 27)
1
2
3
4
5
6
7
8
9
function* powers(n, max) {
  for (let current = n;current <= max; current *= n) {
    yield current;
  }
}

for (let power of powers(3,50)) {
  console.log(power);
}

Initially, when you call powers, the function is frozen at its start. Every time you call next on the iterator (which we are doing during the printing loop), the function runs until it hits a yield expression, which pauses it and causes the yielded value to become the next value produced by the iterator. When the function returns, the iterator is done.

We will end with generators in this chapter. I mentioned this here to see what asynchronous is and does!

1.2. What you will learn

In the next module of this tutorial you will learn
  • what synchronous programming is

  • when you should programm asynchronously and when not

  • know that in JavaScript a lot of code is written asynchronously for several reasons

1.3. Why: Asynchronous Programming

The central part of a computer, the part that carries out the individual steps that make up our programs, is called the processor. The programs we have seen so far are things that will keep the processor busy until they have finished their work. The speed at which something like a loop that manipulates numbers can be executed depends pretty much entirely on the speed of the processor.

But many programs interact with things outside of the processor. For example, they may communicate over a computer network or request data from the hard disk—which is a lot slower than getting it from memory.

When such a thing is happening, it would be a shame to let the processor sit idle—there might be some other work it could do in the meantime. In part, this is handled by your operating system, which will switch the processor between multiple running programs. But that doesn’t help when we want a single program to be able to make progress while it is waiting for a network request.

1.4. What: Asynchronous Programming

In a synchronous programming model, things happen one at a time. When you call a function that performs a long-running action, it returns only when the action has finished and it can return the result. This stops your program for the time the action takes.

An asynchronous model allows multiple things to happen at the same time. When you start an action, your program continues to run. When the action finishes, the program is informed and gets access to the result (for example, the data read from disk).

We can compare synchronous and asynchronous programming using a small example: a program that fetches two resources from the network and then combines results.

In a synchronous environment, where the request function returns only after it has done its work, the easiest way to perform this task is to make the requests one after the other. This has the drawback that the second request will be started only when the first has finished. The total time taken will be at least the sum of the two response times.

The solution to this problem, in a synchronous system, is to start additional threads of control. A thread is another running program whose execution may be interleaved with other programs by the operating system—since most modern computers contain multiple processors, multiple threads may even run at the same time, on different processors. A second thread could start the second request, and then both threads wait for their results to come back, after which they resynchronize to combine their results.

In the following diagram, the thick lines represent time the program spends running normally, and the thin lines represent time spent waiting for the network.

In the synchronous model, the time taken by the network is part of the timeline for a given thread of control. In the asynchronous model, starting a network action conceptually causes a split in the timeline. The program that initiated the action continues running, and the action happens alongside it, notifying the program when it is finished.

control io
Figure 1. Describing synchronous, with threads and async programming

Another way to describe the difference is that waiting for actions to finish is implicit in the synchronous model, while it is explicit, under our control, in the asynchronous one.

Asynchronicity cuts both ways. It makes expressing programs that do not fit the straight-line model of control easier, but it can also make expressing programs that do follow a straight line more awkward. We’ll see some ways to address this awkwardness later in the chapter.

Both of the important JavaScript programming platforms—browsers and Node.js—make operations that might take a while asynchronous, rather than relying on threads. Since programming with threads is notoriously hard (understanding what a program does is much more difficult when it’s doing multiple things at once), this is generally considered a good thing

Since there is no such thing as a free lunch, not using threads comes with a trade-off in this case we have to learn working with callbacks which is the subject of the next module

2. Topic: Callbacks

2.1. Introduction

In the previous module we learned that asynchronous programming can have it’s benefits, when used properly. We introduced the term callback function to have a substitute for threads.

callbacks are the part of this module

2.2. What you will learn

In this module of this tutorial you will learn
  • what a callback is

  • why to use them

  • how to use them

2.3. Why and When: Callbacks

Why we are using callbacks is already answered in the previous module: to have a separate alternative for a thread to do something asynchronous

2.4. What: Callbacks

One common approach to asynchronous programming is to make functions that perform a slow action take an extra argument, a callback function. The action is started, and when it finishes, the callback function is called with the result.

As an example, the setTimeout function, available both in Node.js and in browsers, waits a given number of milliseconds (a second is a thousand milliseconds) and then calls a function.

Example setTimeout
1
setTimeout(() => console.log("Tick"), 500);
Explaining the code above
  • 1: function setTimeout is invoked which expects a callback function and a timeout:int which waits for 500ms and the invokes the callback

Waiting is not generally a very important type of work, but it can be useful when doing something like updating an animation or checking whether something is taking longer than a given amount of time.

Demo (wrong use of function using NO callbacks)
1
2
3
4
5
6
7
8
9
10
11
12
13
function doHomework(){
  // Simulate a code delay
  setTimeout( function(){
    console.log("Doing my homework!"); // you should invoke the callback here! // so pass it in ... see fix.js
  }, 500 );
}
function finishHomeWork(){
  console.log("Finished my homework!");
}


doHomework();
finishHomeWork();
Demo (good use of function using CALLBACK)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// step 1
function doHomework(subject, callback) {

  console.log(`Starting my ${subject} homework.`);

  setTimeout(callback, 1500);
}


// step 3
function finishHomework() {
  console.log(`Finished my homework`);
}

doHomework('math', finishHomework);
doHomework('german', finishHomework);
doHomework('dutch', finishHomework);

// step 2
console.log("Done!!!");

// regular function
let x = function(n) {
  console.log(n);
}


console.log(x);

x(3);


// arrow function (because of the =>)
let y = (n) => {
  console.log(n);
}

console.log(y);

y(25);

2.5. Callbacks: Tips and Tricks

Using a parameter for a callback, method I
1
2
3
4
5
6
7
8
9
10
11
function square(number) {
  console.log(number * number);
}

function printSquare(n) {
  setTimeout(function() {
    return square(n)
  }, 500);
}

printSquare(4);
Using a parameter for a callback, method II (handier?)
1
2
3
4
5
6
7
8
9
10
function square(number) {
  console.log(number * number);

}

function printSquare(n) {
  setTimeout(square, 500, n);
}

printSquare(4);

2.6. Assignment: Callbacks

Target
  • to learn to work with callbacks using a regular function and an arrow function

Roadmap
  • during this exercise you will

    • create a callback function for the setTimeout native JavaScript function which will be invoked after 1500ms

      • prints "invoked my callback" to the console

    • Refactor this callback function to an arrow function

Steps
  • Given this sourcecode

setTimeout(() => {
  ...
}, ...);

setTimeout(myCallback, ...);
  • When

    • I run the code

  • Then

    • the callback function(s) print "invoked my callback" to the console

  • And

    • Refactor this callback function to an arrow function

2.7. Conclusion

During this module we learned how to work with callbacks so that we can make asynchronous code with JavaScript

In a way, asynchronicity is contagious. Any function that calls a function that works asynchronously must itself be asynchronous, using a callback or similar mechanism to deliver its result. Calling a callback is somewhat more involved and error-prone than simply returning a value, so needing to structure large parts of your program that way is not great.

So it would we handy and wise to have a more fluent API for working with asynchronous code and callbacks. They invented the Promise interface for that

And for the last …​ it is impossible/unhandy to handle the return value of the function using callbacks. Therefore they invented the Promise which is the subject of the next module …​

2.8. Follow-up: Callbacks

Below you find for this topic some extra resources to watch after the week the topic Callbacks is introduced during the training

3. Topic: Promise

promise all the things joke

3.1. Introduction

In the previous module we learned working with callbacks but we also saw that is is pretty cumbersome and contagious. There should be a smarter way to work with asynhronous code in JavaScript, luckily there is …​ they invented the Promise interface, which is the subject of this module.

3.2. What you will learn

In this module of the tutorial you will learn
  • Why we need a Promise

  • What a Promise is and does

  • How to program with Promises

  • That Promises are nice programming …​ :-)

3.3. Why: Promise

Working with abstract concepts is often easier when those concepts can be represented by values. In the case of asynchronous actions, you could, instead of arranging for a function to be called at some point in the future, return an object that represents this future event.

This is what the standard class Promise is for.

3.4. What: Promise

A Promise is an object representing the eventual completion or failure of an asynchronous operation. Since most people are consumers of already-created promises, this guide will explain consumption of returned promises before explaining how to create them.

Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.

Stated otherwise A promise is an asynchronous action that may complete at some point and produce a value. It is able to notify anyone who is interested when its value is available.

It is useful to think of promises as a device to move values into an asynchronous reality. A normal value is simply there. A promised value is a value that might already be there or might appear at some point in the future. Computations defined in terms of promises act on such wrapped values and are executed asynchronously as the values become available.

3.5. How: Promise

The easiest way to create a promise is by calling Promise.resolve. This function ensures that the value you give it is wrapped in a promise. If it’s already a promise, it is simply returned—otherwise, you get a new promise that immediately finishes with your value as its result.

Example using the Promise class (single then)
1
2
3
4
5
6
7
8
9
#! /usr/local/bin/node

let fifteen = Promise.resolve(15);

fifteen.then(value => {
  console.log(`Got ${value}`); // <= Got 15
});

console.log("done now");

To get the result of a promise, you can use its then method. This registers a callback function to be called when the promise resolves and produces a value. You can add multiple callbacks to a single promise, and they will be called, even if you add them after the promise has already resolved (finished).

But that’s not all the then method does. It returns another promise, which resolves to the value that the handler function returns or, if that returns a promise, waits for that promise and then resolves to its result.

Example using the Promise class (multiple thens)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// step 1
let fifteen = Promise.resolve(15);

// step 3
fifteen.then(value => {
  console.log(`Got ${value}`); // <= Got 15

  return (value * value);
}).then (n => { // this code is INVOKED when the above is done ... not immediately!!!
  console.log(n);

  return (n+1); // or  ??? Promise.resolve(...) :-)
} ).then (n => {
  console.log(n);
});

// step 2
console.log("Done / Einde programma");
Example showing a promise with a success and failure callback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function successCallback(result) {
  console.log("Audio file ready at URL: " + result);
}

function failureCallback(error) {
  console.log("Error generating audio file: " + error);
}

function createAudioFileAsync(audioSettings) {
  if(audioSettings.sound) {
    return Promise.resolve(audioSettings.volume);// success("sound on!");
  }
  else {
    return Promise.reject(audioSettings.volume);
  }
}

let audioSettings = {
  sound:true,
  volume: 50
}

var promise = createAudioFileAsync(audioSettings);

promise.then(successCallback, failureCallback);

audioSettings.sound = false;
promise = createAudioFileAsync(audioSettings);

promise.then(successCallback, failureCallback);



promise.then(data => {
  console.log("succeeded: "+data)
}, data => {
  console.log("Failed: "+data)
})

audioSettings.sound = true;
promise = createAudioFileAsync(audioSettings);

promise.then(data => {
  console.log("succeeded: "+data)
}, data => {
  console.log("Failed: "+data)
})
Explaining the code above
  • X: Read the code yourself

Example creating shorter code of the example above
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function successCallback(result) {

}

function failureCallback(error) {

}

function createAudioFileAsync(audioSettings) {
  if(audioSettings.sound) {
    return Promise.resolve(audioSettings.volume);// success("sound on!");
  }
  else {
    return Promise.reject(audioSettings.volume);
  }
}

let audioSettings = {
  sound:true,
  volume: 50
}

createAudioFileAsync(audioSettings).then(success => {
    console.log("Audio file ready at URL: " + success);
}, error => {
    console.log("Error generating audio file: " + error);
});


audioSettings.sound = false;

createAudioFileAsync(audioSettings).then(success => {
    console.log("Audio file ready at URL: " + success);
}, error => {
    console.log("Error generating audio file: " + error);
});

3.6. Assignment: Creating a simple promise

(which sometimes is hard enough :-))

Target
  • to learn how to make your first Promise

Roadmap
  • during this exercise you will

    • create a function which returns a Promise which contains your age based on the input of the current year and your birthYear

    • invoke the function and print the value of the Promise to the console

    • when the function is invoked with the current Year being smaller than your birthYear the Promise is rejected

Steps
  • Given I have this piece of sourceCode

// this is the asynchronous, Promise returning function
function getAgeBasedOnCurrentAndBirthYearPromise(current, birth) {
  if(current - birth > 0) {
    ...
  }
  else {
    ...
  }
}


// this is the synchronouse value (int) returning function
function getAge(current, birth) {
  let promisedAge = getAgeBasedOnCurrentAndBirthYearPromise(current, birth);

  // prints Promise { 50} since IT IS A PROMISE
  console.log(promisedAge);

  // now the value please

  promisedAge.then (
    ...,
    ...
  );

}

// should print 50
getAge(2018, 1968);

// should print an error message
getAge(1968, 2018);
  • When

    • I invoke this function getAge(…​, …​)

  • Then

    • that getAge function calls an ASYNCHRONOUS function which returns a PROMISE containing value of my age

Validation
  • my age is printed to the console

3.7. Conclusion

(conclusion of this module) and link to next module During this module we learned how to make (simple) use of the Promise object so that we can use them for asynchronous programming which is very widely used in JavaScript programming and in the upcoming (later) parts of this training (Angular, NodeJS)

Since they use it a lot, there is even a kind of keyword pair designed in JavaScript to handle Promises even simpler (?).

In the following module we will learn that we can use the asyn await construct to handle Promises

3.8. Follow-up: Promise

Below you find for this topic some extra resources to watch after the week the topic Promise is introduced during the training

4. Topic: Async Await

4.1. Introduction

In the previous module we learned that we can use the Promise class for use in asynchronous programming. You might have seen that the .then and success and error have one very big hindrance while programming and that is the very impopulair Goto programming principle. It appears that using Promises we are have a kind of jumping in code …​

Although Promises are used a lot we might also use the very handy async await principle which is the subject of this module.

4.2. What you will learn

In the next module of this tutorial you will learn
  • Why you would want to use the async await JavaScript principle

  • What it is

  • When you should and could use it

  • HOWTO use it

4.3. Why: Async Await

The purpose of async/await functions is to simplify the behavior of using Promises synchronously and to perform some behavior on a group of Promises.

4.4. When: Async Await

You should use the async await if you try to write cleaner code using very little Promise jumps

4.5. What and How: Async Await

Inside a function marked as async, you are allowed to place the await keyword in front of an expression that returns a Promise. When you do, the execution is paused until the Promise is resolved.

Before we dive into it, let’s take a moment to familiarize you with the async/await style. First, async/await makes the asynchronous code appear and behave like synchronous code. Being that it was built on top of Promises, you could simply see it as a new way of writing synchronous code. Just like Promises themselves, async/await is equally non-blocking.

Just as Promises are similar to structured callbacks, one can say that async/await is similar to combining generators and Promises.

Basically, there are two keywords involved, async and await, let’s understand them better:

4.5.1. What and How: Async

Putting the keyword async before a function tells the function to return a Promise.

If the code returns something that is not a Promise, then JavaScript automatically wraps it into a resolved promise with that value e.g when it returns an AsyncFunction object:

This function returns a Promise
1
2
3
async function oddNumber() {
        return 7;
}

Then there’s the second keyword await that makes the function even much better

4.5.2. What and How: Await

The await keyword simply makes JavaScript wait until that Promise settles and then returns its result

let result = await oddNumber();
Note that the await keyword only works inside async functions, otherwise you would get a SyntaxError. From the async function above, let’s have an await example
This statement waits for the completion of the function above
1
2
3
4
5
6
7
8
9
async function oddNumber() {
        return 7;
}


async function printOddValue() {
        let oddValue = await oddNumber(); // invokes the async function oddNumber (above)

        console.log(oddValue); // that's it! :-)

await simply makes JavaScript wait until the Promise settles, and then go on with the result. Meanwhile, as it waits, the engine carries on with performing other tasks like running scripts and handling events. Thus, no CPU resources will be lost.

Demo regarding async with a waiting Promise
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function assert(assertion, message) {
  if(!assertion) {
    throw new Error(message);
  }
}

async function foo()  {
  return "foo";
}

let result = foo();

assert(result instanceof Promise);

console.log(result);

result.then(
  function(result) {
    assert(result === "foo");
    console.log(result);
  }
);

// the / a way to invoke a async function in the "main" part of the application
// in fact I made a function here which I immediately invoke hence it's name
// IIFE (Immediately Invoked Function Expression)
(async () =>{
  result = await foo();
  console.log(result);
})();


// for explained. this is a simple IIFE
(() => {
  console.log("this is an iife, which is from now an a fact of life :-)");
}
)();
Demo regarding await for async method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
async function bar() {
  console.log("in bar");
  return "bar"; // returns Promise {bar}
}

async function printBar() {
  console.log("in printBar");
    let value = await bar();

    console.log(value);
}


printBar();
console.log("end of program");
Demo regarding promise equivalent of bar (so the old way)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function bar() {
  return Promise.resolve("bar"); // returns Promise {bar}
}

function printBar() {
    let promisedValue = bar();

    promisedValue.then(
      value => {
        console.log(value);
      }
    );
}

printBar();
Be aware that you can still return a Promise.resolve(…​) method to return a Promise in as async function. It still is OK, but why would you since the asyc function wraps the value ALWAYS in a Promise. You have to be aware of that!!!

4.6. Assignment: Async Await

In the following assignment you may remove the error when current < birthDate for now
Target
  • to learn how to work with the keyword pair async and await

Roadmap
  • during this exercise you will refactor the Promise-based code in the previous exercise to a async await-based code

Steps
// this is the asynchronous, Promise returning function
// no validation for the current - birth > 2018 for now!!!
... function getAgeBasedOnCurrentAndBirthYearPromise(current, birth) {
  return ...
}


// this is the synchronouse value (int) returning function
... function getAge(current, birth) {
  let promisedAge = getAgeBasedOnCurrentAndBirthYearPromise(current, birth);

  // prints Promise { 50} since IT IS A PROMISE
  console.log(promisedAge);

  // now the value please

   // => can you remove this now?
  promisedAge.then (
    ...,
    ...
  );

}

// should print 50
getAge(2018, 1968);
  • When

    • I refactor this code using the async await based code

  • Then

    • I see the same result as the Promise-based code in the previous assignment

In the above assignment you may remove the error when current < birthDate for now

4.7. Topic: Error handling with async await

Since we are now using the async await principle we created a small problem: What happens when we run into an Error while executing the async function?

The answer is pretty simple and straightforward: we can just use the regular try catch principle in JavaScript to handle the error ⇒ read the following code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
async function getById(input) {
  if (input == 0) {
    throw new Error();
  }
  else {
    return "That rocks: "+input;
  }
}

async function main(input) {
  try {
    let result = await getById(input);

    console.log(result);
  }
  catch(error) {
    console.log("That went pretty wrong! :-()")
  }

}

main(3);
main(0);

4.8. Conclusion

During this module we learned how to make use of the varying asynchronous ways of working with JavaScript so that we can use the much used functionality in the core of JavaScript and NodeJS later on …​ In the following module we will learn that we can (also) make use of Observables which are also a great way to make your life as asynchronous programmer a bit easier

4.9. Follow-up: Async Await

Below you find for this topic some extra resources to watch after the week the topic Async Await is introduced during the training

5. Topic: Generators

5.1. Introduction

In the previous module we learned that we can use async/await to have an asynchronous workflow. We can also use the fancy Generators to have a kind of asynchronous workflow

Working with Generators is the subject of this module

5.2. What you will learn

In the next module of this tutorial you will learn
  • What generators are

  • When to use them

  • How to use them

5.3. Why and When: Generators

Imagine the Ferrari factory; do you think that they make a dozen of Ferrari’s without orders? No …​ they make Ferrari’s when someone has bought one so they have the so-called pull strategy which of course is handy to prevent spending money on never bought cars

That principle is applicable with JavaScript as well using Generators

5.4. What: Generators

The ability of functions to be paused and then resumed again is not exclusive to async functions. JavaScript also has a feature called generator functions. These are similar, but without the promises.

When you define a function with function* (placing an asterisk after the word function), it becomes a generator. When you call a generator, it returns an iterator so we can iterate / loop over it!

5.5. How: Generators

A simple example (printing 3, 9 and 27)
1
2
3
4
5
6
7
8
9
function* powers(n, max) {
  for (let current = n;current <= max; current *= n) {
    yield current;
  }
}

for (let power of powers(3,50)) {
  console.log(power);
}

Initially, when you call powers, the function is frozen at its start. Every time you call next on the iterator (which we are doing during the printing loop), the function runs until it hits a yield expression, which pauses it and causes the yielded value to become the next value produced by the iterator. When the function returns, the iterator is done.

5.6. Assignment: Generators

Target
  • To learn to work with a pretty complicated generator function

Roadmap
  • During this training you will create a generator function to return an iterator containing number from start to end increasing with a step value

Steps
  • Given I have this source code .Description

function ... iterateOverNumbers(start, step, max) {
  for(let n = start;n<=max;n += step) {
    ...
  }
}

// prints nothing  or {}... why not? :-)
// NB: When you do not iterate over an iterator returned from a generator function the code is NOT EXECUTED
let iterator = iterateOverNumbers(0,5,25);

for(let element of iterator) {
  console.log(element);
}
  • When

    • I invoke the code

  • Then

    • The numbers between start and end are printed with step steps

5.7. Conclusion

(conclusion of this module) and link to next module During this module we learned how to make …​ so that …​ we can In the following module we will learn that we can (also) make use of …​

5.8. Follow-up: Generators

Below you find for this topic some extra resources to watch after the week the topic Generators is introduced during the training