Asynchronous Javascript with async/await

Published 2017-05-09

ES2017 async and await keywords to write asynchronous code that is more readable and easier to follow than equivalent code based on long promise chains or deeply nested callbacks.

The await operator takes a promise and then pauses the function execution until that promise is settled which allows for an async function to read like sequential synchronous code.

Write an Asynchronous Function with async/await

With traditional chain of promises:

const fetch = require('node-fetch')

function showGitHubUser(userName) {
  fetch(`http://api.github.com/users/${userName}`)
    .then(data => data.json())
    .then(user => {
      const { name, location } = user

      console.log(name, location)
    })
}

showGitHubUser('qetr1ck-op')

Rewrite to async/await:

const fetch = require('node-fetch')

async function showGitHubUser(userName) {
  const data = await fetch(`http://api.github.com/users/${userName}`)
  const user = await data.json()
  const { name, location } = user

  console.log(name, location)
}

showGitHubUser('qetr1ck-op')

Call an Asynchronous function in a Promise chain

const fetch = require('node-fetch')

async function showGitHubUser(userName) {
  const data = await fetch(`http://api.github.com/users/${userName}`)
  return await data.json()
}

showGitHubUser('qetr1ck-op').then(user => {
  const { name, location } = user

  console.log(name, location)
})

Convert any function into Asynchronous Function

const fetch = require('node-fetch')

class GitHubApiClient {
  // the same syntax with objects
  async fetchUser(handle) {
    const url = `https://api.github.com/users/${handle}`
    const response = await fetch(url)
    return await response.json()
  }
}

// classic iife
;(async () => {
  const client = new GitHubApiClient()
  const user = await client.fetchUser('qetr1ck-op')
  console.log(user.name)
  console.log(user.location)
})()

Handle Errors in Asynchronous Function

const fetch = require('node-fetch')

async function fetchGitHubUser(userName) {
  const response = await fetch(`http://api.github.com/users/${userName}`)

  if (!response.ok)
    throw Error(response.statusText)

  return await response.json()
}

(async () => {
  try {
    const { name, location } = await fetchGitHubUser('unknownuserstring')
    console.log(name, location)
  } catch(e) {
    console.error(e)
  }
})()

Await multiple promises sequentially or concurrently

You can await multiple promises either sequentially or concurrently, depending on where you put the await operators.

const fetch = require('node-fetch')
const measureTime = require('measure-time')

async function fetchGitHubUser(endpoint) {
  const response = await fetch(`http://api.github.com${endpoint}`)

  if (!response.ok) throw Error(response.statusText)

  return await response.json()
}

;(async () => {
  // concurrent
  const t1 = measureTime()
  const user = await fetchGitHubUser('/users/qetr1ck-op')
  const repos = await fetchGitHubUser('/users/qetr1ck-op/repos')

  console.log(`concurrent: ${t1().millisecondsTotal}`)
  console.log(user.name, `repos: ${repos.length}`)
})()

;(async () => {
  // parallel
  const t1 = measureTime()
  const userPromise = fetchGitHubUser('/users/qetr1ck-op')
  const reposPromise = fetchGitHubUser('/users/qetr1ck-op/repos')

  const user = await userPromise
  const repos = await reposPromise

  console.log(`parallel: ${t1().millisecondsTotal}`)
  console.log(user.name, `repos: ${repos.length}`)
})()


;(async () => {
  // parallel vol.2
  const t1 = measureTime()
  const [ user, repos ] = await Promise.all([
      fetchGitHubUser('/users/qetr1ck-op'),
      fetchGitHubUser('/users/qetr1ck-op/repos')
  ])

  console.log(user.name, `repos: ${repos.length}`)
})()

Use the await Operator with Any Thenable

The await operator is not restricted to ES2015 promises. It can be used to await any thenable — that is, any object with a .then() method.

const Bluebird = require("bluebird");

async function main() {
    console.log("Working ...");
    await Bluebird.delay(2000);
    console.log("Done.");
}

main();

Iterate Asynchronously with the for-await-of Loop

An example with ts configuration

Save my day