What is Async/Await?

Async/Await, also known as an asynchronous function, is a token used to control an asynchronous JavaScript process. This has been done in many modern browsers. It was inspired by C# and F# and now Async/Await has landed smoothly in ES2017.

Usually we think of async function as a function that returns promises. You can also use the await keyword in async function. The await keyword can be placed before an expression that needs to return a Promise, and the resulting value is stripped from the Promise for a more intuitive synchronous experience. It’s more intuitive to look at the actual code.

// This is a simple return Promise function
Resolve ("MESSAGE") after 2 seconds.
function getMessage() {
  return new Promise((resolve, reject) = > {
    setTimeout((a)= > resolve("MESSAGE"), 2000);
  });
}
Copy the code
async function start() {
  const message = await getMessage();
  return `The message is: ${message}`;
}
Copy the code
start().then(msg => console.log(msg));
// "The message is: MESSAGE"
Copy the code

Why Async/Await?

Async/Await provides a relatively synchronous looking method to execute asynchronous code. It also provides a concise and intuitive way to handle asynchronous errors, as it implements try… Catch tag, which is one of the most common synchronization modes in JavaScript.

Before we start taking risks, it should be clear that Async/Await is built on JavaScript Promises and it is important to know about them.

About the mark

Async function

To create an async function, we usually place the async keyword before the declared function, like this:

async function fetchWrapper() {
  return fetch('/api/url/');
}

const fetchWrapper = async () => fetch('/api/url/');
Copy the code
const obj = {
  async fetchWrapper() {/ /... }}Copy the code

The Await keyword

async function updateBlogPost(postId, modifiedPost) {
  const oldPost = await getPost(postId);
  constupdatedPost = { ... oldPost, ... modifiedPost };const savedPost = await savePost(updatedPost);
  return savedPost;
}
Copy the code

In this case await is used before any other function that returns a promise. On the first line, oldPost is assigned to the value returned by getPost after the resolve execution. In the next line, we use deconstructed assignment to demonstrate how to merge oldPost and modifiedPost. Finally, we save the POST and return the result of the savedPost.

The sample/FAQ

🖐️ “How do you handle errors?”

That’s a good question! When you use async/await, you can also use try… The catch. As shown below, we fetch something asynchronously and return some kind of error, which we can get in the catch.

async function tryToFetch() {
  try {
    const response = await fetch('/api/data', options);
    return response.json();
  } catch(err) {
    console.log(`An error occured: ${err}`);
    // instead of returning an error
    // We can return an empty data
    return { data: []}; }}Copy the code
tryToFetch().then(data= > console.log(data));
Copy the code

🖐️ ️ “I still don’t know why async/await is better than callbacks/promises.”

I’m glad you asked. Here’s an example to illustrate the difference. We just want to fetch some data asynchronously, and then simply return some processed data after getting the data. If there is an error, we simply want to return an object.

FetchSomeDataCB and processSomeDataCB
// NOTE:CB represent the callback

function doWork(callback) {
  fetchSomeDataCB((err, fetchedData) = > {
    if(err) {
      callback(null, [])
    }

    processSomeDataCB(fetchedData, (err2, processedData) => {
      if(err2) {
        callback(null[]); }// return the processedData outside of doWork
      callback(null, processedData);
    });
  });
}

doWork((err, processedData) = > console.log(processedData));
Copy the code
// We have fetchSomeDataP and processSomeDataP
// NOTE:P means that this function returns a Promise

function doWorkP() {
  return fetchSomeDataP()
    .then(fetchedData= > processSomeDataP(fetchedData))
    .catch(err= > []);
}

doWorkP().then(processedData= > console.log(processedData));
Copy the code
async function doWork() {
  try {
    const fetchedData = await fetchSomeDataP();
    return processSomeDataP(fetchedData);
  } catch(err) {
    return [];
  }
}

doWork().then(processedData= > console.log(processedData));
Copy the code

Callback vs Promise vs Async/Await

🖐️ “How concurrent is he?”

When we need to do something sequentially, we usually declare all the steps one by one with await. To understand concurrency before this, we had to use promise.all. If we now have three asynchronous actions that need to be executed in parallel, we need to make all promises start before adding await.

// This is not the solution, they do it one at a time
async function sequential() {
  const output1 = await task1();
  const output2 = await task2();
  const output3 = await task3();
  return combineEverything(output1, output2, output3);
}
Copy the code

Because the above code only performs three tasks sequentially, rather than concurrently, the latter will rely on the former to complete. So we’re going to reinvent the promise.all approach.

// This can be executed concurrently
async function parallel() {
  const promises = [
    task1(),
    task2(),
    task3(),
  ];
  const [output1, output2, output 3] = await Promise.all(promises); ) ;return combineEverything(output1, output2, output3);
}
Copy the code

In this example, we first performed three asynchronous tasks, then stored the Promise into an array. We use promise.all to complete the collection of concurrent results.

A couple of other hints

  • It’s easy to forget every time youawaitFor some code, you need to declare that this function is aasync function.
  • When you useawaitWhen it paused the value involvedasync function. In other words, the following code will log before anything else'wanna race? '
const timeoutP = async (s) => new Promise((resolve, reject) = > {
  setTimeout((a)= > resolve(s*1000), s*1000)});Copy the code
[1.2.3].forEach(async function(time) {
  const ms = await timeoutP(time);
  console.log(`This took ${ms} milliseconds`);
});
Copy the code
console.log('wanna race? ');
Copy the code

When your first await promise returns an execution result on the main thread, the log outside the forEach will not block.

Browser support

Take a look at this browser support table.

The Node support

Node 7.6.0 and above supports Async/Await!

By Benjamin Diuguid

Asynchronous Adventures in JavaScript: Async/Await

Translation: Dominic Ming