JavaScript Async/Await
Async/await is syntactic sugar built on top of Promises. It allows you to write asynchronous code that looks and behaves like synchronous code, making it easier to read and maintain.
The async Keyword
The async keyword is placed before a function declaration to make it an async function. An async function always returns a promise. If the function returns a value, the promise is resolved with that value.
async function greet() {
return 'Hello, World!';
}
// An async function returns a Promise
greet().then(function(message) {
console.log(message);
});
// Equivalent to:
function greetPromise() {
return Promise.resolve('Hello, World!');
}
greetPromise().then(function(message) {
console.log('Promise version: ' + message);
});The await Keyword
The await keyword can only be used inside an async function. It pauses the execution of the async function until the promise is resolved, and then returns the resolved value.
function delay(ms) {
return new Promise(function(resolve) {
setTimeout(resolve, ms);
});
}
async function demo() {
console.log('Starting...');
await delay(1000);
console.log('After 1 second');
await delay(1000);
console.log('After 2 seconds');
return 'Done!';
}
demo().then(function(result) {
console.log(result);
});Error Handling with try/catch
With async/await, you can use standard try/catch blocks to handle errors, just like synchronous code. This replaces the .catch() method used with promises.
function fetchData(shouldFail) {
return new Promise(function(resolve, reject) {
if (shouldFail) {
reject(new Error('Data fetch failed!'));
} else {
resolve({ id: 1, name: 'Product' });
}
});
}
async function getData() {
try {
const data = await fetchData(false);
console.log('Success: ' + data.name);
const bad = await fetchData(true);
console.log('This will not run');
} catch (error) {
console.log('Caught: ' + error.message);
}
}
getData();Async Arrow Functions
You can also create async arrow functions. The async keyword comes before the parameter list.
const fetchUser = async (id) => {
return { id: id, name: 'User ' + id };
};
const processUser = async (id) => {
const user = await fetchUser(id);
console.log('Processing: ' + user.name);
return user;
};
processUser(42).then(function(user) {
console.log('Result: ' + JSON.stringify(user));
});Sequential vs Parallel Execution
By default, multiple await statements run sequentially. To run promises in parallel, use Promise.all() with await. This is important for performance when tasks are independent.
function fetchItem(name, ms) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(name);
}, ms);
});
}
// Sequential (slower)
async function sequential() {
const a = await fetchItem('A', 100);
const b = await fetchItem('B', 100);
console.log('Sequential: ' + a + ', ' + b);
}
// Parallel (faster)
async function parallel() {
const [a, b] = await Promise.all([
fetchItem('A', 100),
fetchItem('B', 100)
]);
console.log('Parallel: ' + a + ', ' + b);
}
sequential();
parallel();| Feature | Promises | Async/Await |
|---|---|---|
| Syntax | .then()/.catch() | await / try-catch |
| Readability | Chain-based | Looks synchronous |
| Error handling | .catch() | try/catch |
| Debugging | Harder (async stack) | Easier (step through) |
| Parallel execution | Promise.all() | await Promise.all() |