What is Async/Await?
Async/Await, also known as an asynchronous function, is a token used to control an asynchronous JavaScript process. This has been done in many modern browsers. It was inspired by C# and F# and now Async/Await has landed smoothly in ES2017.
Usually we think of async function as a function that returns promises. You can also use the await keyword in async function. The await keyword can be placed before an expression that needs to return a Promise, and the resulting value is stripped from the Promise for a more intuitive synchronous experience. It’s more intuitive to look at the actual code.
// This is a simple return Promise function
Resolve ("MESSAGE") after 2 seconds.
function getMessage() {
return new Promise((resolve, reject) = > {
setTimeout((a)= > resolve("MESSAGE"), 2000);
});
}
Copy the code
async function start() {
const message = await getMessage();
return `The message is: ${message}`;
}
Copy the code
start().then(msg => console.log(msg));
// "The message is: MESSAGE"
Copy the code
Why Async/Await?
Async/Await provides a relatively synchronous looking method to execute asynchronous code. It also provides a concise and intuitive way to handle asynchronous errors, as it implements try… Catch tag, which is one of the most common synchronization modes in JavaScript.
Before we start taking risks, it should be clear that Async/Await is built on JavaScript Promises and it is important to know about them.
About the mark
Async function
To create an async function, we usually place the async keyword before the declared function, like this:
async function fetchWrapper() {
return fetch('/api/url/');
}
const fetchWrapper = async () => fetch('/api/url/');
Copy the code
const obj = {
async fetchWrapper() {/ /... }}Copy the code
The Await keyword
async function updateBlogPost(postId, modifiedPost) {
const oldPost = await getPost(postId);
constupdatedPost = { ... oldPost, ... modifiedPost };const savedPost = await savePost(updatedPost);
return savedPost;
}
Copy the code
In this case await is used before any other function that returns a promise. On the first line, oldPost is assigned to the value returned by getPost after the resolve execution. In the next line, we use deconstructed assignment to demonstrate how to merge oldPost and modifiedPost. Finally, we save the POST and return the result of the savedPost.
The sample/FAQ
🖐️ “How do you handle errors?”
That’s a good question! When you use async/await, you can also use try… The catch. As shown below, we fetch something asynchronously and return some kind of error, which we can get in the catch.
async function tryToFetch() {
try {
const response = await fetch('/api/data', options);
return response.json();
} catch(err) {
console.log(`An error occured: ${err}`);
// instead of returning an error
// We can return an empty data
return { data: []}; }}Copy the code
tryToFetch().then(data= > console.log(data));
Copy the code
🖐️ ️ “I still don’t know why async/await is better than callbacks/promises.”
I’m glad you asked. Here’s an example to illustrate the difference. We just want to fetch some data asynchronously, and then simply return some processed data after getting the data. If there is an error, we simply want to return an object.
FetchSomeDataCB and processSomeDataCB
// NOTE:CB represent the callback
function doWork(callback) {
fetchSomeDataCB((err, fetchedData) = > {
if(err) {
callback(null, [])
}
processSomeDataCB(fetchedData, (err2, processedData) => {
if(err2) {
callback(null[]); }// return the processedData outside of doWork
callback(null, processedData);
});
});
}
doWork((err, processedData) = > console.log(processedData));
Copy the code
// We have fetchSomeDataP and processSomeDataP
// NOTE:P means that this function returns a Promise
function doWorkP() {
return fetchSomeDataP()
.then(fetchedData= > processSomeDataP(fetchedData))
.catch(err= > []);
}
doWorkP().then(processedData= > console.log(processedData));
Copy the code
async function doWork() {
try {
const fetchedData = await fetchSomeDataP();
return processSomeDataP(fetchedData);
} catch(err) {
return [];
}
}
doWork().then(processedData= > console.log(processedData));
Copy the code
Callback vs Promise vs Async/Await
🖐️ “How concurrent is he?”
When we need to do something sequentially, we usually declare all the steps one by one with await. To understand concurrency before this, we had to use promise.all. If we now have three asynchronous actions that need to be executed in parallel, we need to make all promises start before adding await.
// This is not the solution, they do it one at a time
async function sequential() {
const output1 = await task1();
const output2 = await task2();
const output3 = await task3();
return combineEverything(output1, output2, output3);
}
Copy the code
Because the above code only performs three tasks sequentially, rather than concurrently, the latter will rely on the former to complete. So we’re going to reinvent the promise.all approach.
// This can be executed concurrently
async function parallel() {
const promises = [
task1(),
task2(),
task3(),
];
const [output1, output2, output 3] = await Promise.all(promises); ) ;return combineEverything(output1, output2, output3);
}
Copy the code
In this example, we first performed three asynchronous tasks, then stored the Promise into an array. We use promise.all to complete the collection of concurrent results.
A couple of other hints
- It’s easy to forget every time you
await
For some code, you need to declare that this function is aasync function
. - When you use
await
When it paused the value involvedasync function
. In other words, the following code will log before anything else'wanna race? '
。
const timeoutP = async (s) => new Promise((resolve, reject) = > {
setTimeout((a)= > resolve(s*1000), s*1000)});Copy the code
[1.2.3].forEach(async function(time) {
const ms = await timeoutP(time);
console.log(`This took ${ms} milliseconds`);
});
Copy the code
console.log('wanna race? ');
Copy the code
When your first await promise returns an execution result on the main thread, the log outside the forEach will not block.
Browser support
Take a look at this browser support table.
The Node support
Node 7.6.0 and above supports Async/Await!
By Benjamin Diuguid
Asynchronous Adventures in JavaScript: Async/Await
Translation: Dominic Ming