Skip to content

TIL - Asynchronous Programming

Posted on:August 13, 2023 at 11:05 AM

Today, I am writing a TIL post on asynchronous programming. It’s something that I’ve learned last year and have been reviewing repeatedly… And yet, I would always say I only vaguely knew it. This time around, with the help of Eunjae’s Sinabro JavaScript course as well as a Korean book on how to become a Node.js backend developer, there were definitely moments where I got a better grasp of an understanding.

To solidify my takeaways, this TIL is on asynchronous programming such as callbacks, Promises, and async/await.

JavaScript is single-threaded - it can only work on one thing at a time

Asynchronous vs. Synchronous:

Synchronous:

Asynchronous:

If you have an asynchronous operation on TOP of a console.log(“hello”), because it takes time for the asynchronous operation to run, the asynchronous function is pushed to the side of the main flow and the next line of code runs. Therefore, with asynchronous operations, the results of codes don’t necessarily show in the console in a top-down fashion. If you wanted the console.log to run AFTER the asynchronous operation is done, you would pass it into the callback function.

However, if you have a series of steps that should follow an asynchronous operation (rather than run before the asynchronous function is complete), using callbacks would result in callback hell (numerous number of indentations that each denotes a callback).

Important Note: console.log(Promise) and Promise.then(console.log) is different

Promise.all()

If your multiple promises don’t necessarily need to be run in an order, and/or a promise doesn’t rely or depend on the result of another promise, but you’d like to see their results, you can use Promise.all().

One thing to note about Promise.all() is that if any of the Promises in the array is rejected, the Promise.all() also is rejected. If you would like to see the rest of the results of the promises even if one of them is rejected, you would use Promise.allSettled().

Async & await


// fetch request
const promise = fetch(url)

// not using await keyword
const response1 = promise; 
console.log({response1}) // you get a Promise value

// using await keyword 
const response2 = await promise;
console.log({response2}) // you get the actual returned value of a fulfilled Promise

Thing to note about an async function that has a return value with await keyword

Let’s take a look at the code below (code is provided by Eunjae from his course).

// first example without async/await keyword
function getTodo(id) {
  return fetch(url)
}


console.log('getTodo(1)', getTodo(1)); 

The result of the console.log would be a Promise, since fetch returns a Promise. This means that you wouldn’t be receiving a final value of a fulfilled Promise.

Let’s now try to recreate this function into an asynchronous function using await and async.


async function getTodoAsync(id) {
  return await fetch(url)
}

console.log('getTodoAsync(1)', getTodoAsync(1))

You may think that the log of this function would return an actual value since await is used. Surprisingly, it still returns a Promise.

This is because the function is declared as an async function. An async function will always return a promise, no matter what it contains. The return value has await, which means the function would pause its execution until the promise returned by fetch(url) is resolved. Even so, the getTodoAsync function will still return a promise.

Examples of methods or functions that return promises