async and await

The ECMAScript 2017 specification introduced new concepts to the JavaScript language in the form of the async and await keywords. The async keyword is used to designate a function as asynchronous:

async function getNumber() {
return 42;
}

Doing this, effectively, wraps whatever the function returns in Promise (if it is not already Promise). So, if we attempt to call this function we will receive Promise:

getNumber() instanceof Promise; // => true

As we've learned, we can subscribe to the fulfillment of Promise by using its then method:

getNumber().then(number => {
number; // => 42
});

In concert with async functions that return Promises, we also have an await keyword. This enables us to wait for the fulfillment (or rejection) of the Promise simply by passing it to the right side of await. This may, for example, be a Promise returned from an async function call:

await someAsyncFunction();

Or it may be a Promise designated inline, like so:

const n = await new Promise(fulfill => fulfill(123));
n; // => 123

As you can see, the await keyword will wait for its Promise to resolve and thereby prevents any following lines from executing until that occurs.

The following is another example—a setupFeed async function that awaits both fetch() and response.json():

async function setupFeed() {
const response = await fetch('/data');
const json = await response.json();
console.log(json);
}

It's important to note that the await keyword does not block like alert() or prompt(). Instead, it simply pauses the execution of the asynchronous function, freeing up the Event Loop to continue with other work, and then, when its Promise resolves, it will continue execution where it left off. Remember, await is only syntactic sugar over functionality that we can already achieve. If we wanted to implement our setupFeed function without async/await, we could easily do that by reverting to our old pattern of passing callbacks to Promise#then:

function setupFeed() {
fetch('/data').then(response => {
return response.json()
}).then(json => {
console.log(json);
});
}

Observe how the code is slightly clunkier and more congested when we don't use await. Using await in concert with asynchronous functions gives us the same satisfyingly linear and procedural appearance as regular synchronous code. This can vastly simplify an otherwise complicated asynchronous control flow, making it clearer to our fellow programmer what is happening when

The await keyword is also available for use within the for...of iteration construct. Doing so will await each value iterated over. If, during iteration, any encountered value is a Promise, the iteration will not continue until that Promise has been resolved:

const allData = [
fetch('/data/1').then(r => r.json()),
fetch('/data/2').then(r => r.json()),
fetch('/data/3').then(r => r.json())
];

for await (const data of allData) {
console.log(data);
}

// Logs data from /data/1, /data/2 and /data/3

Without Promises or await and async, expressing this kind of asynchronous process would require not only also more code but also more time to understand. The beauty of these constructs and abstractions is that they allow us to ignore the implementation details of asynchronous operations, enabling us to focus purely on expressing our problem domain. As we move forward in this book, we will further explore this spirit of abstraction as we tackle some larger and more unwieldy problem domains.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.152.58