Appearance
Async Functions
In JavaScript, asynchronous operations require using Promises. A Promise object operates asynchronously when performing network operations, invoking a callback function upon completion: if successful, it calls then()
, and if there’s an error, it calls catch()
. While this asynchronous implementation prevents the user from feeling that the page is "stuck," writing multiple then()
and catch()
statements can be cumbersome and messy.
Is there a simpler way to write this?
You can use the async
keyword in conjunction with await
to call Promises, allowing asynchronous operations to resemble synchronous code:
javascript
async function get(url) {
let resp = await fetch(url);
let result = await resp.json();
return result;
}
Using async function
defines an asynchronous function, and asynchronous functions can be seen as equivalent to Promises. Inside an async function
, you can use await
to call another asynchronous function, which makes the syntax similar to synchronous code while executing asynchronously.
In other words:
javascript
let resp = await fetch(url);
Automatically implements asynchronous calling, which is equivalent to the following Promise code:
javascript
let promise = fetch(url);
promise.then((resp) => {
// Handle resp
});
What if we want to implement catch()
? The Promise approach would look like this:
javascript
let promise = fetch(url);
promise.then((resp) => {
// Handle resp
}).catch(e => {
// Handle error
});
When using await
, you can simply employ traditional try { ... } catch
syntax:
javascript
async function get(url) {
try {
let resp = await fetch(url);
let result = await resp.json();
return result;
} catch (e) {
// Handle error
}
}
By defining asynchronous functions with async
and calling them with await
, the code resembles synchronous writing while greatly enhancing readability.
It’s crucial to note that await
calls must occur within an async function
and cannot be invoked in traditional synchronous code. So, how can a synchronous function call an async function
?
Firstly, calling an asynchronous function directly with await
in a regular function will result in an error:
javascript
async function get(url) {
let resp = await fetch(url);
return resp.json();
}
function doGet() {
let data = await get('/api/categories'); // This will throw an error
}
doGet();
If you remove await
, the function executes, but you won't receive the result directly, since you'll only get a Promise object:
javascript
async function get(url) {
let resp = await fetch(url);
let result = await resp.text();
return result;
}
function doGet() {
let promise = get('./content.html');
console.log(promise); // Logs a Promise object
}
doGet();
Therefore, when calling an async function
from a regular function, you cannot use await
, but you can call the async function
directly to obtain the Promise object and then chain then()
and catch()
to handle the results or errors:
javascript
async function get(url) {
let resp = await fetch(url);
let result = await resp.text();
return result;
}
function doGet() {
let promise = get('./content.html');
promise.then(data => {
// Handle data
document.getElementById('test-response-text').value = JSON.stringify(data);
});
}
doGet();
Response Results:
Thus, when defining asynchronous tasks, using async function
is simpler than using Promises. When invoking asynchronous tasks, using await
is more straightforward than using Promises, and capturing errors with the traditional try...catch
syntax is also easier than using Promises. As long as the browser supports it, you can effectively implement asynchronous operations in a concise manner with async
.