In the previous few posts we have discussed on Promise in JavaScript and how it helps to solve the issues related to callbacks resulting in more readable and maintainable code.In this post we will discuss on the async and await keywords which are nothing but a syntactic sugar coat on Promise leading to a more streamlined and maintainable code.

The async functions are declared with the async keyword and await keyword is permitted within the async functions.

The async functions always returns a Promise object which will be:

  • Resolved with the value returned by async function
  • Rejected with the exception thrown by the async function.

We have defined a very simple async function below which returns the square of its input.

image

This function will return a Promise which will resolve with a square of its input value and will be rejected if the input value is negative.

image

The above program will have the following output:

image

If we pass a negative value then the Promise will be rejected as shown below.

image

image

So this async function is quite similar to the following:

image

Note, that using the async keyword will simplify the above code to a great extent.

The await keyword is permitted only within an async function and is used to wait on an Promise or any other value. If it’s waiting on an Promise the return value will be the fulfilled value of a Promise or any other value.

We have created a promisified version of the squared function as shown below.

image

We will now use await keyword and invoke this from an async function as shown below:

image

This code will print the following clearly indicating that await call is waiting about 1 sec for the Promise to get resolved.

image

If we invoke this with a negative value it will have the following output:

image

image

This is because await keyword throws the rejected value of the Promise which should be handled properly as shown below:

image

    In the last post, we have seen how we can sequentially execute promises using Promise chaining via the Promise.resolve and Array.prototype.reduce functions. In this post, we will see how we can execute the promises in parallel using the Promise.all function.

    As per documentation the Promise.all does the following:

    The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will resolve when all of the input’s promises have resolved, or if the input iterable contains no promises. It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.

    We will use the similar tasks as we had used in the previous post but here we will go for parallel execution instead of sequential.

    image

    image

    image

    Note that Task3 has minimum timeout period and Task2 has maximum.

    Now we will create an array (iterable) of promises by executing these three tasks with an input value.

    image

    We will invoke the Promise.all method using this promises array.

    image

    The output will be as follows:

    image

    The timings clearly shows that:

    • Tasks are started and executed almost in parallel
    • Task3 is completed early , followed by Task1 and then Task2 based on their timeout interval of the setTimeout function.
    • The returned promise i.e. aggrPromise is resolved when all input promises are resolved and the results are printed as per their order in the input array.

    image

    The returned promise rejects immediately if any of the input promises is rejected. We will examine this by passing a negative value to the third function as shown below:

    image

    The output will be as follows:

    image

    We can see that both Task1 and Task2 are completed but the resultant promise rejects immediately with the error message.

    image

    In the previous post, we have seen Promises can be chained together by returning another Promise object from the onFulfilled parameter of the then function. The chain of Promises executes sequentially. So we can easily build a sequential execution workflow by building a chain of Promises. But before getting into there we will take a detour and examine the Promise.resolve and Array.prototype.reduce functions.

    As per documentation, Promise.resolve does the following:

    The Promise.resolve(value) method returns a Promise object that is resolved with a given value. If the value is a promise, that promise is returned; if the value is a thenable (i.e. has a "then" method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned promise will be fulfilled with the value.

    Let’s quickly check this out with few code snippets.

    image

    Here the parameter value is a number and returned promise will be fulfilled with the value as shown below:

    image

    Next, we will pass a thenable as parameter, thenable is an object with a then function. Note, all promises are thenables but all thenables are not promise.

    image

    Here the returned Promise object will follow the thenable and execute the then function as shown below:

    image

    In the code below we are passing a Promise object to the resolve function and it will be fulfilled executing the resolve callback as shown below:

    image

    imageL

    Lastly, we will invoke the resolve function without passing any value.

    image

    image

    So the call to the resolve function without passing any value returns a Promise object which auto resolves without any data ( undefined ). Please note this, as we will use this Promise.resolve() call to initialize our Promise chain while prepare for sequential execution.

    As per documentation, Array.prototype.reduce does the following:

    The reduce() method executes a user-supplied “reducer” callback function on each element of the array, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.

    The definition of the reduce function is as follows:

    • reduce(callbackFn)
    • reduce(callbackFn, initialValue)

    The callback or reducer function accepts the following arguments:

    • previousValue (the value resulting from the previous call to callback or reducer function)
    • currentValue (the value of the current element)
    • currentIndex [Optional]
    • array [ Optional ]

    The following example shows a simple usage of the reduce function to compute sum of the elements of an array of numbers.

    image

    We will now use the Promise.resolve and Array.prototype.reduce functions to execute an array of promises in sequence.

    We have defined three functions returning Promises as shown below.

    image

    image

    image

    The array tasks contains the above functions as it’s elements.

    image

    Now we will chain these promises together using the reduce function as shown below:

    image

    The execution of this code will print the following:

    image

    The timings clearly indicates a sequential execution. But we can see that the result of the last task is not printed. This is because the then function is not called on the Promise object that is returned by the reduce function.

    If we add the following lines of code we can all results will get printed properly as shown below.

    image

    image

    In the previous post, we have discussed about the basics of Promise, here we will take a deeper look into the Promise.then function.

    The code below shows the promisified version of the add function which simply adds two numbers.

    image

    This will print the following as expected.

    image

    In the previous post we have seen that the Promise.then function comes with the following signature Promise.then(onFulfilled, onRejected). But what is the return value ? It returns another Promise object.

    So what does the returned Promise object do in the code snippet above?. It does nothing but simply auto resolves without any data because the then function does not return anything.

    This can be verified by invoking the then function on the Promise object returned by the invocation of the then function of the addPromise.

    image

    The output will be:

    image

    The first then function does return anything so the Promise object returned auto-resolves with an undefined value.

    Now what happens if the then function returns a value? We have now changed the code so that then function of addPromise return the square of the result. Note, here we are returning simply a value not another Promise object.

    image

    The output will be:

    image

    The Promise object returned by then function call on addPromise auto-resolves with the returned value.

    So if a then function returns a value then the Promise object will simply auto resolve with the returned value.

    The then function returning another Promise object provides with the capability to chain the Promises and execute them in sequence as shown below:

    image

    Here the flow of execution is as shown below:

    image

    NOTE: This is completely differently from defining multiple then handlers for a promise.

    image

    In the above code different handlers receive the same data from the resolve callback and execute parallelly.

    image

    Now we will explore the condition where a then function returns another Promise object.

    We have created another promisified version of Math.pow as shown below.

    image

    This Promise object is now returned instead of directly returning the value as shown below:

    image

    In this case the next then function will be executed with the fulfilment value of the returned Promise object if it is resolved or, the rejection value / error will be processed in the catch.

    The above code will print the following:

    image

    If we pass a negative value to powPromise object, the chain will break with an error as shown below.

    image

    The above code will print the following:

    image

    As we have discussed earlier callbacks are the basic building blocks of asynchronous programming in JavaScript/Node.js , they are used for notifying when an asynchronous operation is completed. But callbacks when used directly comes with a set of problems like Callback Hell and complex and less-maintainable code required to implement the asynchronous control flows from scratch ( obviously a library like async can be of help here).

    Promise(s) are considered to be the next step of improvement on top of bare continuation passing style (CPS) callbacks. Promise is an object that contains the status of an asynchronous operation and eventually the result ( success / failure). A Promise object has three states:

    • Pending – When the asynchronous operation is in-progress.
    • Fulfilled – When the asynchronous operation is successfully completed.
    • Rejected – When the asynchronous operation is terminated with an error.

    We need to use Promise.then method to receive and use the result of fulfilment or, error. The Promise.then method comes with the following signature Promise.then(onFulfilled, onRejected).

    The Promise constructor creates a new Promise object accepting two function objects as input:

    new Promise(( resolve, reject ) => {….})

    • resolve (obj) – This function is invoked when the Promise is fulfilled.
    • reject (obj) – This function is invoked when the Promise is terminated with an error.

    We will start exploring Promise with it’s constructor and the “then” function. But first let’s start with an example with callback and then we will develop a Promise based version of the same.

    image

    The code below shows the Promise based version of the greater than (gt) function. Here, the gtPromise function returns a new Promise object and the resolve callback is invoked in case of successful execution and reject callback is executed in case of an error.

    image

    Now we need consume i.e. execute or use this Promise by passing the resolve and reject callbacks using the then function.

    image

    We can refine the above code by using the Promise.catch(onRejected) which is nothing but a syntactic sugar coat on Promise.then (null, onRejected).

    image

    In the above example we transformed a callback based function by returning a Promise object. This process is known as promisification.

    In the next post we will take a look into how promises can be chained together.

      The two common asynchronous control flow patterns include sequential and parallel flows.

      In the sequential flow, the tasks are executed one after the other in sequence and delay in one causes a delay in the start of the subsequent tasks.These can be a set of independent tasks without sharing any data among them or, they can be chained where the output of the preceding task is used as the input of the subsequent one (waterfall or, pipeline).

      image

      In parallel flow, the tasks are executed in parallel not in any specified order.

      image

      The above control flows can be implemented very easily using the async library. The three important functions that we will explore are:

      • async.series
      • async.parallel
      • async.waterfall

      The async.series function accepts two arguments:

      a) tasks – This can be array of functions or an object

      b) callback – This is the optional callback function with two arguments error, results. The results parameter is an array which contains the result argument passed to the callback by each of the tasks.

      In the code below we have three functions passed as the first argument and the callback function simply prints the elements of the result array passed to the callback.

      image

      The output will be as follows:

      image

      If we increase the timeout interval in the second function to 200 ms then the start of the third function is delayed. This clearly indicates the sequential execution.

      image

      I will now use the same code but I will invoke async.parallel instead of series.

      image

      The below output clearly shows that tasks are started and running simultaneously.

      image

      Now we will explore the async.waterfall function. This function also like series executes the tasks / functions sequentially but output of one function is passed as input to the next as shown below:

      image

      The output will be:

      image