Today we’ll talk about the async/await group of apis

Async /await is an ES7 standard, Promise is an ES6 standard, the ASYNc /await API is also used to help us write asynchronous code, it is built on Promise, kind of like Okhttp and Retrofit

What is Async?

async function myFirstAsyncFunction() {
  try {
    const fulfilledValue = await doSomeThing()
  }
  catch (rejectedValue) {
    / /...}}Copy the code

It looks something like this. Async is generally not used alone, but with await. An async function may have zero or more await inside.

This code is easy to read even if you haven’t learned Promise. This is where async functions come in handy.

When async is called, it immediately returns a Promise.

await

Await cannot be used alone and an error is reported if called from inside a non-async function. “Await” is followed by a Promise. It can be something else, such as a number, or a variable, or a function. If await is not followed by a Promise, a resolve Promise is returned.

When an async function executes to await, the whole async function is suspended and given control, and the process is resumed only after the promise-based asynchronous operation it is waiting for has been fulfilled or rejected.

Of course, async functions also return a Promise, that is, await can also be followed by an async function.

The async/await API feels like coroutines and pending functions in Kotlin.

Why async?

Hide promises to make them easier to understand


function logFetch(url) {
  return fetch(url)
    .then(response= > response.text())
    .then(text= > {
      console.log(text)
    }).catch(err= > {
      console.error('fetch failed', err)
    })
}
Copy the code

If using async function to write, perhaps looks like this:

async function logFetch(url) {
  try {
    const response = await fetch(url)
    console.log(await response.text())
  }
  catch (err) {
    console.log('fetch failed', err)
  }
}
Copy the code

Although the number of lines is about the same, the code looks much cleaner, with much less then nesting. Requesting an interface data and then printing it, as you can see, is simple.

Just like in the previous example, if you haven’t learned Promise, you can still read and understand async code. This seems to be nothing, but for a large project, the technical level of personnel is uneven, so it is not possible to ensure that everyone is familiar with and understand Promise. What we should do is to reduce the difficulty of understanding the code as much as possible, so that most people can understand it

Write asynchronous logic with synchronous thinking


The above code is still relatively simple, so let’s take a more complicated example.

We want to get the size of a network resource, which might look something like this if we use Promise:

function getResponseSize(url) {
  return fetch(url).then(response= > {
    const reader = response.body.getReader()
    let total = 0

    return reader.read().then(function processResult(result) {
      if (result.done) return total
      const value = result.value
      total += value.length
      console.log('Received chunk', value)
      return reader.read().then(processResult)
    })
  })
}
Copy the code

Even if you’ve learned Promise, this code isn’t easy to understand, let alone for those of you who haven’t. Because there is a loop in the middle, and the execution of the process is asynchronous, which is not solved by a chain call that we learned earlier. Of course, you can also extract it to make the code a little bit cleaner.

const processResult = (result) = >{
  if (result.done) return total
  const value = result.value
  total += value.length
  console.log('Received chunk', value)
  return reader.read().then(processResult)
}

function getResponseSize(url) {
  return fetch(url).then(response= > {
    const reader = response.body.getReader()
    let total = 0
    return reader.read().then(processResult)
  })
}
Copy the code

But there is one more way, just barely. But let’s look at how async functions are handled.

async function getResponseSize(url) {
  const response = await fetch(url)
  const reader = response.body.getReader()
  let result = await reader.read()
  let total = 0
  while(! result.done) {const value = result.value
    total += value.length
    console.log('Received chunk', value)
    // get the next result
    result = await reader.read()
  }
  return total
}
Copy the code

OHHHHHHHHH

Does this look more fluid? Because await expressions block execution and even block loops directly, the code that looks synchronous overall is more intuitive and easier to read.

Watch out for await blocking

Since await blocks async functions, the code looks more like synchronous code and is easier to read and understand. Beware of await blocking, however, because some blocking is unnecessary and improper use can affect the performance of your code.

If we were to merge network data with local data, an example of an error might look like this:

async function combineData(url, file) {
    let networkData = await fetch(url)
    let fileData = await readeFile(file)
    console.log(networkData + fileData)
}
Copy the code

Instead of waiting for one file to finish reading and then reading the next file, we can read both files together and then merge them to make our code run faster. We can write this:

async function combineData(url, file) {
    let fetchPromise = fetch(url)
      , readFilePromise = readFile(file)
      , networkData = await fetchPromise
      , fileData = await readFilePromise
    console.log(networkData + fileData)
}
Copy the code

In this way, the network can simultaneously request and read files, which can save a lot of time. This takes advantage of the fact that promises are implemented as soon as they are created, so for those of you who don’t know what we did in the last section, please review.

Of course, if you are familiar with promises, you can use the promise. all method directly, or await after promise. all will not be expanded here.

Exception handling

try… catch

In async functions, exception handling is typically a try… Catch, if no try is made… Once the catch, await expression is reject, the async function returns a Promise, reject.

In conjunction with promises, if a Promise state is settled as Reject, and subsequent THEN passes no REJECT or catch, then an exception is thrown. From this perspective, using try… in async functions A catch wraps an await expression, possibly catching the exception and passing the reject message inside the catch. I won’t give you any examples here.

Links: juejin. Cn/post / 696700… Source: Nuggets