DEV Community

Cover image for Async and Await in Vanilla JavaScript
Emanuele Bartolesi for This is Learning

Posted on

Async and Await in Vanilla JavaScript

In the last couple of years I work a lot with Blazor WebAssembly for my personal projects and, first of all, for my main job.
Time to time I need to invoke some JavaScript code to perform some specific operations.
In this case I never use a specific JavaScript framework, so many functions I have to do in vanilla JavaScript.

If you have ever worked with asynchronous code in JavaScript, you probably know how challenging it can be to handle callbacks, promises, and errors. Fortunately, there is a syntactic feature that can make your life easier: async and await.

Async and await are keywords that allow you to write asynchronous code in a more readable and concise way. They are based on promises, but they let you avoid the nesting and chaining of then() and catch() methods. Instead, you can use the await keyword to pause the execution of an async function until a promise is resolved or rejected. This way, you can write asynchronous code as if it was synchronous.

How to use async and await

To use async and await, you need to do two things:

  • Declare an async function with the async keyword before the function name or the arrow function.
  • Use the await keyword inside the async function to wait for a promise to resolve or reject.

Here is a simple example of an async function that fetches some data from an API and logs the result in the console:



async function fetchData() {
  let response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
  let data = await response.json();
  console.log(data);
}

// Call the async function
fetchData();


Enter fullscreen mode Exit fullscreen mode

Notice how the code looks like synchronous code, even though it is performing asynchronous operations. The await keyword makes the JavaScript engine pause the execution of the async function until the promise is settled. Then, it resumes the execution with the resolved value of the promise.

You can also use try...catch blocks to handle errors in async functions, just like in synchronous code. For example:



async function fetchData() {
  try {
    let response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
    let data = await response.json();
    console.log(data);
  } catch (error) {
    // Handle the error
    console.error(error);
  }
}


Enter fullscreen mode Exit fullscreen mode

Pros of async and await

Using async and await can have several benefits for your code quality and readability:

  • It reduces the boilerplate code and indentation that comes with using promises and callbacks.
  • It makes the code more linear and intuitive, as it follows the natural flow of execution.
  • It improves the error handling, as you can use standard try...catch blocks instead of catch() methods or rejection callbacks.
  • It makes it easier to debug the code, as you can use breakpoints and step through the code as if it was synchronous.

Cons of async and await

While async and await are very useful and powerful features, they also have some caveats that you should be aware of:

  • You can only use await inside an async function. If you try to use it outside an async function, you will get a syntax error.
  • An async function always returns a promise, even if you don't explicitly return one. This means that you need to use then() or await to get the value returned by an async function.
  • Using await will block the execution of the current async function, but not the whole program. Other functions or events that are not dependent on the awaited promise will still run in the background.
  • You should avoid using await in loops or parallel tasks, as it will make your code run sequentially instead of concurrently. Instead, you should use Promise.all() or Promise.race() to wait for multiple promises at once.

You can find more information about Promise.all() and Promise.race() here.

Conclusion

Async and await can improve your code quality and readability, as well as your error handling and debugging experience. However, they also have some caveats that you should be aware of, such as using them only inside async functions, handling their return values properly, and avoiding them in loops or parallel tasks.

If you want to learn more about async and await, you can check out the following link: MDN Web Docs: Async functions


Are you interested in learning GitHub but don't know where to start? Try my course on LinkedIn Learning: Learning GitHub.

LinkedIn Learning


Thanks for reading this post, I hope you found it interesting!

Feel free to follow me to get notified when new articles are out 🙂

Top comments (9)

Collapse
 
brense profile image
Rense Bakker

Small note though, you cannot do actual concurrency in JavaScript unless you use worker threads or webworkers. Promises will only let you continue execution of other code, while the awaited promise isnt doing any execution. For example when its just waiting for some event to happen like a setTimeout or setInterval. If code is being executed inside the awaited promise, for example when looping over a million array items, your awaited promise will block execution of other code, since JavaScript is single threaded.

Collapse
 
tracygjg profile image
Tracy Gilmore

Excellent introduction to Promises and Async/Await. Readers might be interested in developer.mozilla.org/en-US/docs/W...

Collapse
 
doniarobinson profile image
Donia Robinson

I really appreciate the second pro here. They read much more intuitively to me, and it avoids a ton of nesting!

Collapse
 
kjsisco profile image
kjsisco

This is such a simple method. Thank you for this!

Collapse
 
wudixer profile image
Steffen Lips

The third point on Cons is in fact a pro. If await would block the whole program, then there would bei no real benefit using asynchronous functions.
And it ist only async not concurrent. Everything is executed in the main thread so you don't have to care about locking.

Collapse
 
samuel_kelv profile image
Samuel Kelv

If promise does not implement concurrency why then do program below the promise function execute first before the promised function?

Collapse
 
pierrewahlberg profile image
Pierre Vahlberg

Try reading up on javascript engines micro and macro task queues and the event loop and call stack in general,.once you learn that (on a brief level) you can start to discuss why when and where promises solve issues 🔥

Collapse
 
codingjlu profile image
codingjlu • Edited

I'm just wondering, if you're trying to demonstrate async/await in vanilla JS, what's the non-vanilla equivalent (that sounds like more standardized)?

Collapse
 
pierrewahlberg profile image
Pierre Vahlberg

Its nowadays a language feature and, to my knowledge, there is no well adapted abstraction on it. Async/await (syntax sugar for promises) is vanilla and I think the author means to point out that this is a framework-less method to write code that reads well and executes smoothly (if implemented right)