Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

Asynchronous Programming

Javascript code generally handles network & IO operations asynchronously: instead of blocking on a file read or database call, a callback is called when the data is ready.

There are three main ways of handling this in Javascript (and therefore Typescript) programs: callbacks, promises, and async/await.


Use async/await.

It looks like this:

async function readAndPrint(): Promise<void> {
  const data = await readFilePromised("myfile")

await readAndPrint()

Synchronous Methods

If writing a script (rather than a server) you can probably use synchronous variants of methods, if they're available:

const data = fs.readFileSync("myfile");


Callbacks look like:

readFileCallback("myfile", (data: string) => {

Even though foo appears before bob in the code, in almost all cases, bob will be printed before foo.

Callbacks lead to what's called callback hell:

readDirectory("mydir", (eachFile: string) => {
  getFilePermissions(eachFile, (canReadFile: boolean) => {
    if (canReadFile) {
      readFileCallback(eachFile, (data: string) => {


Promises came after callbacks. Instead of being passed a function to call once complete, promises return a variable that you can call .then or .catch on:

readFilePromised("myfile").then((data: string) => console.log(data))

Promises help with callback hell but can become very confusing when dealing with exceptions.


async/await are syntactic sugar that wraps promises and make asynchronous code easier to read and make exceptions more predictable to deal with.

There's a good introduction at the MDN: Making asynchronous programming easier with async and await

Any Javascript library that supports promises supports async/await.

If the library uses callbacks, you can use promisify to wrap it in promises and then use it with async/await: util.promisify

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment