4.1 The async Keyword
Asynchronous functions in JavaScript let you write async code that looks and reads like synchronous code.
The async
and await
keywords, introduced in ECMAScript 2017 (ES8), make working with promises
easier and make the code more readable and manageable.
Main Concepts
The async
keyword before a function declaration indicates that the function is asynchronous. An async
function always returns a promise, even if you don't explicitly use the return
operator inside it.
If the function returns a value, it's automatically wrapped in a promise with that value.
Syntax:
async function name() {
// function code
}
Example:
async function greet() {
return 'Hello, world!';
}
greet().then((message) => {
console.log(message); // Logs: Hello, world!
});
4.2 The await Keyword
The await
keyword is used inside an async function to pause its execution until a promise is resolved.
You can only use await
inside functions declared with the async
keyword.
Syntax:
let result = await
promise;
Example:
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function greet() {
await delay(2000);
return 'Hello, world!';
}
async function displayGreeting() {
const message = await greet();
console.log(message); // Logs: Hello, world! after 2 seconds
}
displayGreeting();
4.3 Examples of Using async and await
Example 1: Async Function Awaiting Multiple Promises
function fetchData1() {
return new Promise((resolve) => setTimeout(() => resolve('Data 1'), 1000));
}
function fetchData2() {
return new Promise((resolve) => setTimeout(() => resolve('Data 2'), 2000));
}
async function fetchAllData() {
const data1 = await fetchData1();
console.log(data1); // Logs: Data 1 after 1 second
const data2 = await fetchData2();
console.log(data2); // Logs: Data 2 after 2 seconds
}
fetchAllData();
Example 2: Parallel Execution of Asynchronous Operations
To execute multiple async operations in parallel, you can use Promise.all()
with await
.
function fetchData1() {
return new Promise((resolve) => setTimeout(() => resolve('Data 1'), 1000));
}
function fetchData2() {
return new Promise((resolve) => setTimeout(() => resolve('Data 2'), 2000));
}
async function fetchAllData() {
const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
console.log(data1); // Logs: Data 1 after 2 seconds
console.log(data2); // Logs: Data 2 after 2 seconds
}
fetchAllData();
Example 3: Error Handling with try...catch
Async functions let you use try...catch
blocks for error handling, making the code more readable and manageable.
function fetchDataWithError() {
return new Promise((resolve, reject) => setTimeout(() => reject('Error occurred'), 1000));
}
async function fetchData() {
try {
const data = await fetchDataWithError();
console.log(data);
} catch (error) {
console.error('Error:', error); // Logs: Error: Error occurred after 1 second
}
}
fetchData();
Example 4: Using async and await in Class Methods
You can also use async functions in class methods.
class DataFetcher {
async fetchData() {
const data = await new Promise((resolve) => setTimeout(() => resolve('Fetched Data'), 1000));
return data;
}
}
const fetcher = new DataFetcher();
fetcher.fetchData().then((data) => {
console.log(data); // Logs: Fetched Data after 1 second
});
Example 5: Asynchronous Iterators
Async iterators let you work with streams of data that come in asynchronously.
async function* asyncGenerator() {
let i = 0;
while (i < 3) {
await new Promise((resolve) => setTimeout(resolve, 1000));
yield i++;
}
}
async function iterateAsyncGenerator() {
for await (let value of asyncGenerator()) {
console.log(value); // Logs 0, 1, and 2 with a 1-second interval
}
}
iterateAsyncGenerator();
GO TO FULL VERSION