Async functions are an ECMAScript proposal by Brian Terlson. It is at stage 3 (candidate).
Before I can explain async functions, I need to explain how Promises and generators can be combined to perform asynchronous operations via synchronous-looking code.
For functions that compute their one-off results asynchronously, Promises, which are part of ES6, are becoming increasingly popular. One example is the client-side fetch
API, which is an alternative to XMLHttpRequest for retrieving files. Using it looks as follows:
function fetchJson(url) {
return fetch(url)
.then(request => request.text())
.then(text => {
return JSON.parse(text);
})
.catch(error => {
console.log(`ERROR: ${error.stack}`);
});
}
fetchJson('http://example.com/some_file.json')
.then(obj => console.log(obj));
co is a library that uses Promises and generators to enable a coding style that looks more synchronous, but works the same as the style used in the previous example:
const fetchJson = co.wrap(function* (url) {
try {
let request = yield fetch(url);
let text = yield request.text();
return JSON.parse(text);
}
catch (error) {
console.log(`ERROR: ${error.stack}`);
}
});
Every time the callback (a generator function!) yields a Promise to co, the callback gets suspended. Once the Promise is settled, co resumes the callback: if the Promise was fulfilled, yield
returns the fulfillment value, if it was rejected, yield
throws the rejection error. Additionally, co promisifies the result returned by the callback (similarly to how then()
does it).
Async functions are basically dedicated syntax for what co does:
async function fetchJson(url) {
try {
let request = await fetch(url);
let text = await request.text();
return JSON.parse(text);
}
catch (error) {
console.log(`ERROR: ${error.stack}`);
}
}
Internally, async functions work much like generators, but they are not translated to generator functions.
The following variants of async functions exist:
async function foo() {}
const foo = async function () {};
let obj = { async foo() {} }
const foo = async () => {};