Trending Technologies

IoT has become a hot topic in the present tech-driven world. A strong framework of cloud computing, backed up by a seamless blending of sensors and actuators with the environment around us, is making…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




The Basics

Since its official inception in ES8, async/await has become a centerpiece for the future of JavaScript . Everyday new NPM packages get converted to support promises, promises that then power the all new yet relatively old syntax (C# anyone?), nowadays you can even find util.promisify in Node.js’ core to allow for easy conversion of callbacks to promises.

Before we get into running in parallel and limiting items in a loop let’s get back to the basics. A common pattern with async await is to simply wait for a promise, get its value and continue the function, let’s assume we want to get a user and based on the user object fetch the particular feed, this can be done easily by tagging our getUser function with async and using await before each promise-returning function call:

To demonstrate this let’s write a promise that throws at around a 100 milliseconds at all times:

We can catch errors from this promise in an async function using the traditional try/catch block, although the line following will throw a synchronous error it will never be reached:

Much like catch in promise you can catch an error occurring within the flow:

Whether you are running tasks in parallel, scheduling a loop or creating a cascading structure or a pipeline async/await can simplify what your process translates to in code with efficient and readable control flows. Let’s go through some of the common patterns:

There is no particular syntax to parallel execution with async/await but we can utilize Promise#all against an array (or any iterable) of promises to get the expected results:

Promise#all combines a list of promises into a single promise that will return all values resolved by those promises in an array when the promises have all been resolved. This happens in parallel and we don’t need any other trickery beyond this simple and elegant function.

Perhaps the least sung hero of async/await is the promisified timeout. It is effective and essential, especially when used within the context of a loop (see delayed loop below), we can wrap traditional timers (setTimeout, setImmediate) in promises like below:

We can then put these functions into action by creating a async pause (non-process-blocking) between two functions regardless of whether or not they are synchronous or asynchronous:

This way we never have to leave the function’s context, this can lead to more elegant code when used appropriately.

Control flows are dead simple with async/await but my personal favorite practice of async/await is loops, a simple async loop can be represented in multiple ways and of course we will follow this up with parallel execution.

A loop through a given number of items that performs a number of asynchronous actions, in our example below stop the loop on each step to fetch some data from the database and log the results and then continue to the next item, going one by one, thus creating a series loop:

We can utilize the concept of timeouts within our loop, for example if we wanted to create a method that would add a random number to an array once a second for a total of 10 seconds we could use either setTimeout or setImmediate with a counter or a for loop awaiting the timeoutPromise we implemented earlier:

and we can even go as far as implementing a conditional setInterval with a while loop:

If it runs in parallel, parallelize. Parallel loops can be created by pushing a promise into an array that will later resolve into a value thus all promises start at the exact same time and can take their own time to finish, the final results will be ordered automatically by Promise#all:

This can be more elegantly represented with Array#map, and it helps that we get a little more functional with our implementation for real-world use-cases, by mapping the array of items into an array of promises and awaiting the values:

Promise#race will return a promise that will resolve when the first item in a given list of promises resolves.

A simple race can be created by passing a list of promises which in the following case would be the return of an async function that resolves in a random amount of time:

The first promise to resolve will win the race and get collected as our result.

We can utilize nearly all that we have covered so far to build a function that executes other async functions in parallel with a given limit. A real-life example of this would be to process screenshots of a list of webpages only 5 at a time.

To achieve this with promises and pure async/await we’ll need to have a way to store promises which are currently in-flight or in other words have not yet been resolved. Unfortunately this is not available as part of spec-grade promises so we’ll instead use a Set to store and delete promises that are in-flight:

We can then utilize Set.size to check the total number of in-flight promises, allowing us to determine how many more iterations of our loop we can continue to schedule.

Next we’ll use Promise#race as part of our control-flow arsenal. What we need is a way to stop iteration of the loop (in this case Array#map) until the next promise has been resolved (we’ll use a race for this) and check if the total number of in-flight promises is less than the limit that we are looking for, if it isn’t then we continue back with another race. This is easy to achieve with the following while loop:

Combining the two together and we’ll end up with parallelLimit (Go ahead you can run this last bit) :

The impact of async/await is still debatable to JavaScript and Node but nevertheless the implications are huge. Async/await is powered by years of expertise using nearly perfected promises and syntax as sweet as it gets* while maintaining much of the core asynchronous concepts that Node popularized. One thing is for sure, it is here to stay and I hope this article was an ice-breaker to what is possible with just a few lines of async/await code.

Add a comment

Related posts:

Eastern charts forecasting market reversal or consolidation in Bitcoin

Utilizing the most popular kind of Japanese chart, the candlestick chart we can gather different findings when using different times scales. On a weekly chart we are forming are third doji…

Exploring the Importance of Universal Sutures in Healthcare Sector

In the world of medicine, Universal Sutures play a pivotal role in wound closure and surgical procedures. These small threads, carefully woven through tissues, have a significant impact on patient…