DEV Community

Cover image for Async/Await, What's That? (JavaScript)
Peyton Strahan
Peyton Strahan

Posted on

Async/Await, What's That? (JavaScript)

Async/Await, an Introduction and Origin Story
The keywords of “async” and “await” are used in conjunction with promises. A simple understanding of the two keywords can be summed up as “async” forces whatever is returned from a function to be a promise, while “await” forces a function to wait for a resolved promise before it can resume running. The history behind these two keywords is a little muddy, but these keywords most likely appeared first in a 2011 version of C# called “Async CTP”. There’s a bunch of moments in history where async/await was implemented into another programming language, but all you need to know is that async/await is in JavaScript (which is what we’ll be using in this blog) among many other languages.

Promises
Promises are objects that represent data that may not be known at the time of the promise’s creation, allowing the data to be returned from an asynchronous method immediately and then used later on when the data is finished resolving. Promises can be in one of three states: pending (meaning the promise is still waiting to be resolved), fulfilled (meaning that an action was committed successfully, and the desired data was retrieved), or rejected (meaning that an action failed to occur properly). Two important methods used with promises are the .then() method (which takes in a “fulfilled” callback function and an optional “error” callback) and the .catch() method (which takes in a single “error” callback function to call when the promise is rejected). The usual process of making a new promise and then using .then() and .catch() is what async/await aims to build upon.

Async
The syntax for using “async” goes as follows:

async function functionName() {
  return "This is a string";
}
Enter fullscreen mode Exit fullscreen mode

The function and use of “async” is very simple: place “async” in front of a normal function declaration, and whatever is returned from calling said function becomes a promise. That’s it. Things get a bit more complicated when we go on to the “await” keyword.

Await
The “await” keyword can only be used within an “async” function declaration, and it is used to force the function to pause at the location of the “await” keyword until a resolved promise is provided, allowing the rest of the function to run. To be more exact, the “await” keyword is written before some reference to the promise that you are waiting to be resolved so it can be used in that part of the “async” function. This can be used to replace .then() because the “await” keyword actually returns the result of a resolved promise and allows you to do whatever you want with the data given from the promise, simulating the effects of .then(). For the “await” keyword to handle errors, some form of .catch() or .then() must be used. The upcoming examples should hopefully make this more clear.

Examples
An example using the “async” syntax and .then():

async function someFunction() {
  return "This is either a string or a promise";
}

console.log('promise: ' + someFunction());

someFunction().then(
  function(value) {console.log('string: ' + value);},
  function(error) {console.log(error);}
)
Enter fullscreen mode Exit fullscreen mode

An example utilizing async/await to handle a promise that can only be resolved:

function resolveIn3Sec() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('resolved');
    }, 3000);
  });
}

async function asyncCall() {
  console.log('waiting');
  const response = await resolveIn3Sec();
  console.log(response);
  // Expected output: "resolved"
}

asyncCall();
Enter fullscreen mode Exit fullscreen mode

An example utilizing async/await to handle a promise that can be resolved or rejected:

function resolveIn3Sec(code) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if(code !== 811){
        reject('rejected');
      } else {
        resolve('resolved');
      }
    }, 3000);
  });
}

async function asyncCall() {
  console.log('waiting');
  try {
    const response = await resolveIn3Sec(821);
    console.log(response);
  } catch (err) {
    console.log(err);
  }
  // Expected output: "rejected"
};

asyncCall();
Enter fullscreen mode Exit fullscreen mode

Image description
Analogy
You can think of async/await as a sort of mail delivery service. The function with the “async” keyword is what is responsible for sending out promises, which is similar to when a shipping company sends out a delivery driver to pick up a package from a seller and then deliver it to the customer. The driver can either successfully pick up the package and send it to the customer (promise fulfilled) or encounter problems when trying to obtain the package from the seller or keeping track of the package when driving to the customer, resulting in the customer getting no package (promise rejected). The “await” keyword waits for a promise to resolve before continuing a function, which is similar to a carpenter waiting on a new hammer to arrive in the mail before he can continue his job.

Image description
Conclusion
The keywords of “async” and “await” are tools used to create promise-based code in a way that makes it resemble synchronous code. The keyword “async” causes a function to return a promise, while “await” causes an “async” function to wait for a promise to resolve before it continues to run. Async/await can serve as an arguably cleaner alternative to using only .then() and .catch() in certain situations, but both methods have their small ups and downs that can appeal to different people.

Links to Resources Used

Top comments (0)