In ECMAScript 2017, async functions and await keywords have been added to the JavaScript language, essentially syntactic candy for Promise, making asynchronous code easier to implement and code readable. It’s worth learning about this new API to make asynchronous code look more like synchronous code, and this article will hopefully help you understand async and await.
What are async and await
async
Let’s start with the async keyword. When you put async in front of a function declaration, the function becomes async, a bit like the GO language defines coroutines. So what is async?
To put it simply, an asynchronous function is a function declared with the async keyword and allowed to use the await keyword in it. The async and await keywords mean that the promise behavior is asynchronous and can be written in a more concise style without explicitly declaring the promise chain.
function resolveAfter2Seconds() {
return new Promise(resolve= > {
setTimeout(() = > {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
const result = await resolveAfter2Seconds();
console.log(result);
// expected output: "resolved"
}
asyncCall();
Copy the code
Executing the above code will now print calling on the console and wait 2 seconds for console.log(result) to be executed when result returns, It feels as if await will stop execution on this line of code until a value is returned and console.log(result) will be executed down.
function hello() { return "Hello" };
console.log(hello());
Copy the code
There’s nothing to explain in the above code, sequential execution immediately prints “Hello” in the console
Try typing the following lines in your browser’s JS console.
async function hello() { return "Hello" };
console.log(hello());
Copy the code
let hello = async() = > {return "Hello" };
hello().then((value) = > console.log(value));
Copy the code
When a function is preceded by the async keyword, it returns a promise rather than a value. Hello ().then((value)=> console.log(value))
The await keyword
It is only when the async and await keywords are combined that the benefits of asynchronous functions become apparent. Await only works in asynchronous functions in regular JavaScript code, but can also be used in JavaScript modules alone.
Await can precede any asynchronous function of a promise to suspend the line’s code until the promise is fulfilled, and then return the result value.
You can use await when calling any function that returns a Promise, including Web API functions.
Refactor the Promise code with async/await
fetch('http://10.1.0.67:5000/get_image')
.then(response= > {
if(! response.ok) {throw new Error(`HTTP error! status: ${response.status}`);
}
return response.blob();
})
.then(myBlob= > {
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
})
.catch(e= > {
console.log('There has been a problem with your fetch operation: ' + e.message);
});
Copy the code
By now, you should have some idea of what promises are and how promises work. Let’s convert asynchronous request code using Promises to async/await code and see why async/await simplifies asynchronous programming.
async function myFetch() {
let response = await fetch('http://10.1.0.67:5000/get_image');
if(! response.ok) {throw new Error(`HTTP error! status: ${response.status}`);
}
let myBlob = await response.blob();
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
}
myFetch()
.catch(e= > {
console.log('There has been a problem with your fetch operation: ' + e.message);
});
Copy the code
The code is much simpler to read and write from top to bottom instead of.then() logic everywhere.
Since the async keyword turns a function into a promise, you can either refactor your code or replace the original code with both promise and await, separating the rest of the function logic and placing it in the then block to be flexible.
async function myFetch() {
let response = await fetch('http://10.1.0.67:5000/get_image');
if(! response.ok) {throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.blob();
}
myFetch().then((blob) = > {
let objectURL = URL.createObjectURL(blob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
}).catch(e= > console.log(e));
Copy the code
You’ll notice that you wrap your code around a function and add the async keyword to the function. Run your asynchronous code in this defined asynchronous function; As mentioned earlier, await is only executed in asynchronous functions, otherwise an exception is thrown.
//Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
let response = await fetch('http://10.1.0.67:5000/one');
Copy the code
In the definition of the myFetch() function, you can see that the code is very similar to the previous version of Promise, although there are certainly differences. Instead of ending every promise-based method with a. Then () and executing logic in it, you just need to prefix the asynchronous request method call with an await keyword and assign the result to a variable. The await keyword causes the JavaScript runtime to pause on this line until the asynchronous function call returns its result, and the code can then use the return value to further manipulate it.
Once asynchronous code, such as a request for a return value, continues execution on the next line.
let response = await fetch('http://10.1.0.67:5000/get_image');
Copy the code
When the network request put back response is available, the respone returned by the fetch() promise will be assigned to a variable, the parser pauses on this line until the response is available, and the parser moves on to the next line to create a Blob. This line is also a method of an asynchronous function, so it is natural to use await. Return the result of the operation from myFetch() when it returns.
This means that when myFetch() is called, a Promise object is returned, so you can call.then() from that promise object to implement the bloB displayed on the screen in the then method.
Add error handling
For error handling, the following options are listed
- You can use synchronous
try... catch
The structure andasync/await
This example is an extension of the code we showed above.
async function myFetch() {
try {
let response = await fetch('http://10.1.0.67:5000/get_image');
if(! response.ok) {throw new Error(`HTTP error! status: ${response.status}`);
}
let myBlob = await response.blob();
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
} catch(e) {
console.log(e);
}
}
myFetch();
Copy the code
Catch () {} catch is passed to an error object, e, which outputs the error message on the console. From e we get detailed error information, including the location in the code where the error was thrown.
You want to use the second (refactored) version of the code we showed above, which mixes.then() with.catch() at the end to catch the error message.