Here is an example that show you why you have to use async/await especially in many callback functions in a single task. Assume that we have a function which multiply ‘x’ by 2 (200 ms).

output = x * 2

Here is the function with a callback parameter.

function slowDoubleCallback(x, callback) { setTimeout(() => { callback(x * 2); }, 200); }

If we would like to call it 10 times, in callback version would be like this:

// Callback Hell Version let callBackAns = 0; slowDoubleCallback(1, (ans) => { callBackAns += ans; slowDoubleCallback(2, (ans) => { callBackAns += ans; slowDoubleCallback(3, (ans) => { callBackAns += ans; slowDoubleCallback(4, (ans) => { callBackAns += ans; slowDoubleCallback(5, (ans) => { callBackAns += ans; slowDoubleCallback(6, (ans) => { callBackAns += ans; slowDoubleCallback(7, (ans) => { callBackAns += ans; slowDoubleCallback(8, (ans) => { callBackAns += ans; slowDoubleCallback(9, (ans) => { callBackAns += ans; slowDoubleCallback(10, (ans) => { callBackAns += ans; console.log("Callback: " + callBackAns); }); }); }); }); }); }); }); }); }); });

That is horrible, right? Now, make a Promise version. To do this, we need to modify the function to return Promise object:

function slowDouble(x) { return new Promise((resolve) => { setTimeout(() => { resolve(x * 2); }, 200); }); }

To call it 10 times, would be like this:

// Promise Version let promiseAns = 0; slowDouble(1).then((ans) => { promiseAns += ans; return slowDouble(2); }).then((ans) => { promiseAns += ans; return slowDouble(3); }).then((ans) => { promiseAns += ans; return slowDouble(4); }).then((ans) => { promiseAns += ans; return slowDouble(5); }).then((ans) => { promiseAns += ans; return slowDouble(6); }).then((ans) => { promiseAns += ans; return slowDouble(7); }).then((ans) => { promiseAns += ans; return slowDouble(8); }).then((ans) => { promiseAns += ans; return slowDouble(9); }).then((ans) => { promiseAns += ans; return slowDouble(10); }).then((ans) => { console.log("Promise: " + (promiseAns + ans)); });

Much better in Promise version? Now in async/await version:

// async / await Version (async () => { let ans = 0; ans += await slowDouble(1); ans += await slowDouble(2); ans += await slowDouble(3); ans += await slowDouble(4); ans += await slowDouble(5); ans += await slowDouble(6); ans += await slowDouble(7); ans += await slowDouble(8); ans += await slowDouble(9); ans += await slowDouble(10); console.log("async/await: " + ans); })();

Extremely clear, isn’t it? Not just for readability. You could add for-loop here like structured programming which is difficult in callback/ promise (Edit: a redditor pointed out that you can do this with Promise) version.

// async / await Version 2 (async () => { let ans = 0; for (let i = 1; i <= 10; i++) { ans += await slowDouble(i); } console.log("async/await Version 2: " + ans); })();

Hope you could feel the benefit of async/await after read the example. Not saying callback is useless, it is still useful in a simple situation. However, it is much clear to write async/await in complicated situation.

Tested on: Node.js 8.10.0

Gist:

https://gist.github.com/louislam/a4ffc57fb9fd4596a0092d1054eabcee

Reddit Thread:

https://www.reddit.com/r/javascript/comments/85j6tu/for_beginners_i_wrote_an_article_to_help_you/