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();
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);
}
}
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.
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)
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.
Excellent introduction to Promises and Async/Await. Readers might be interested in developer.mozilla.org/en-US/docs/W...
I really appreciate the second pro here. They read much more intuitively to me, and it avoids a ton of nesting!
This is such a simple method. Thank you for this!
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.
If promise does not implement concurrency why then do program below the promise function execute first before the promised function?
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 🔥
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)?
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)