JavaScript async await

A js async function can be used as a way to define a special kind of asynchronous function. These kinds of functions still operate in the main event loop, so they still can not be used as a way to achieve true threading with javaScript, at least not by themselves.

1 - js async basic example

The async keyword can be used in combination with the function keyword to declare an async function. Inside the body of the async function the await keyword can be used as a way to pause the execution of the rest of the logic in the function until a function that was called with await is completed.

A basic example of an async function in javaScript might then look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let foo = (delay) => {
return new Promise((resolve) => {
setTimeout(function () {
resolve();
}, delay);
})
};
let func = async function() {
console.log('start');
await foo(3000);
console.log('end');
};
func();

The foo function returns a promise that resolves after a delay. When used inside the body of the func async function that execution of code is paused, and thus the string end is not logged to the console until the delay has completed.

2 - Not a replacement for WebWorker and child_process

An async function still operates in the main javaScript event loop, so it is not a way to go about accomplishing what is often called true threading in javaScript. However there are was of doing that these days with javaScript, just not with async await, at least not by itself anyway.

In this section I will be writing about the subject of async await and true threading in javaScript.

2.1 - Async functions will still hode up the event loop

So an async function that has some code in it that might hold up the event loop will do so just like that of any other function in javaScript. This is because just like any other function in javaScript, we are still dealing with a single event loop. That is unless we take advantage of something that allows for us to create an additional event loop.

For example take into account the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// async function that does something heavy
let heavyAsync = async function () {
var i = Math.pow(10, 9);
while (i--) {}
console.log('bar');
};
// loop
let i = 0, st;
let loop = function () {
setTimeout(loop, 250);
st = new Date();
if (i % 10 === 5) {
heavyAsync();
}
console.log('tick' + i, ' time: ' + (new Date() - st));
i += 1;
};
loop();

In this example when the heavyAsync function is called it still ends up delaying the whole application. This is because I am still just working with a single event loop.

2.2 - However in nodejs the child_process module can help avoid that

In nodejs there is the child_process built in module. This can be used to launch an application from the command line, including node itself. When doing so it results in an additional, independent process on the operating system. Thus it is a way to do something involving more than one event loop with javaScript, thus it is a kind of so called trude threading that differs from what is typical when it comes to async functions, setTiemout, and so forth by itself.

1
2
3
4
5
6
7
let heavyAsync = async function () {
var i = Math.pow(10, 9),
st = new Date();
while (i--) {}
console.log('heavy time: ', new Date() - st);
};
heavyAsync();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let spawn = require('child_process').spawn;
let startHeavy = () => {
let heavy = spawn('node', ['heavy.js']);
heavy.stdout.on('data', function (data) {
console.log(data.toString());
});
};
let i = 0, st;
let loop = function () {
setTimeout(loop, 250);
st = new Date();
if (i % 10 === 5) {
startHeavy();
}
console.log('tick' + i, ' time: ' + (new Date() - st));
i += 1;
};
loop();

So then this example, unlike the first one that just makes use of async await, does not hold up the main javaScript event loop.