Modern asynchronous JavaScript with Async and Await

Explore modern methods of asynchronous functions in JavaScript. The development time of JavaScript from callbacks to Promises is very short, and because ES2017 asynchronous JavaScript uses async/await syntax, it is even simpler

Introduction

JavaScriptIn a short period of time, it developed from a callback topromise(ES2015), andES2017Using async/await syntax, asynchronous JavaScript is even simpler.

Asynchronous functions are Promise andgenerator, Basically, they are a higher-level abstraction of Promise. Let me repeat:Asynchronous/await is based on promise.

Why introduce asynchrony/await?

They reduce the model of fulfilling promises and reduce the limitations of the "non-breaking chain" of fulfilling promises.

When Promises were introduced in ES2015, they were designed to solve the problem of asynchronous code, and they did, but in the two years separating ES2015 and ES2017, it became clear thatPromises cannot be the final solution.

Introduced the resolution of the famous promiseCallback hellProblem, but they themselves introduced complexity and grammatical complexity.

They are good primitives and can expose better syntax to developers, so when the time is right, we canAsynchronous function.

They make the code look synchronous, but in the background it is asynchronous and non-blocking.

How it works

The asynchronous function returns a Promise, such as the following example:

const doSomethingAsync = () => {
  return new Promise(resolve => {
    setTimeout(() => resolve('I did something'), 3000)
  })
}

When you wantcallThis feature is your favoriteawait, withThe calling code will stop until the promise is resolved or rejected. One caveat: the client function must be defined asasync. This is an example:

const doSomething = async () => {
  console.log(await doSomethingAsync())
}

A simple example

This is a simple example of async/await for running a function asynchronously:

const doSomethingAsync = () => {
  return new Promise(resolve => {
    setTimeout(() => resolve('I did something'), 3000)
  })
}

const doSomething = async () => { console.log(await doSomethingAsync()) }

console.log(‘Before’) doSomething() console.log(‘After’)

The above code will print the following to the browser console:

Before
After
I did something //after 3s

Promise all the things

Prepending the async keyword to any function means that the function will return a promise.

Even if it’s not doing so explicitly, it will internally make it return a promise.

This is why this code is valid:

const aFunction = async () => {
  return 'test'
}

aFunction().then(alert) // This will alert ‘test’

and it’s the same as:

const aFunction = async () => {
  return Promise.resolve('test')
}

aFunction().then(alert) // This will alert ‘test’

The code is much simpler to read

As you can see in the example above, our code looks very simple. Compare it to code using plain promises, with chaining and callback functions.

And this is a very simple example, the major benefits will arise when the code is much more complex.

For example here’s how you would get a JSON resource, and parse it, using promises:

const getFirstUserData = () => {
  return fetch('/users.json') // get users list
    .then(response => response.json()) // parse JSON
    .then(users => users[0]) // pick first user
    .then(user => fetch(`/users/${user.name}`)) // get user data
    .then(userResponse => userResponse.json()) // parse JSON
}

getFirstUserData()

And here is the same functionality provided using await/async:

const getFirstUserData = async () => {
  const response = await fetch('/users.json') // get users list
  const users = await response.json() // parse JSON
  const user = users[0] // pick first user
  const userResponse = await fetch(`/users/${user.name}`) // get user data
  const userData = await userResponse.json() // parse JSON
  return userData
}

getFirstUserData()

Multiple async functions in series

Async functions can be chained very easily, and the syntax is much more readable than with plain promises:

const promiseToDoSomething = () => {
  return new Promise(resolve => {
    setTimeout(() => resolve('I did something'), 10000)
  })
}

const watchOverSomeoneDoingSomething = async () => { const something = await promiseToDoSomething() return something + ’ and I watched’ }

const watchOverSomeoneWatchingSomeoneDoingSomething = async () => { const something = await watchOverSomeoneDoingSomething() return something + ’ and I watched as well’ }

watchOverSomeoneWatchingSomeoneDoingSomething().then(res => { console.log(res) })

Will print:

I did something and I watched and I watched as well

Easier debugging

Debugging promises is hard because the debugger will not step over asynchronous code.

Async/await makes this very easy because to the compiler it’s just like synchronous code.


More js tutorials: