Use 'Promises' | Async/Await | in place of JavaScript Callbacks.

Use 'Promises' | Async/Await | in place of JavaScript Callbacks.

We should use Promises which allows us to access asynchronous method and return values to synchronous methods. and Async/Await is the extension of promises.

We are here to..

  • Understand what `Synchronous` and `Asynchronous`.
  • Understand `Callback` - with an Example.
  • Understand `Promises` - with an Example.
  • Understand `Async/Await` - with an Example.

** This article covers very basics of above topics. You'll easily understand at the end about the concept and able to implement it.


Synchronous

When we execute a task synchronously, JE wait for that task to finish before moving on to the next line of code.
(JE: JavaScript Engine.)

Asynchronous

When we execute a task asynchronously, the JE moves the program to the next line of code before the task finishes.

Think of synchronous programming is like waiting in a queue/standing in a line.
and asynchronous programming is like taking a token to buy a ticket and you can go do other things and you'll be notified when your turn comes.

In this Article our focus is on Asynchronous programming.


#1 Callbacks
One way of doing things `asynchronously` is by using callbacks.
We pass a function as an argument to an asynchronous function, and that passed function is called `callback` which will call when the task is completed.

Means we don't want to wait for a task to finish. The next line of code is allowed to execute and that callback function will be call when the task finish.
That `task` could be fetching data from `database` or anything.

• Example-1 ↓

<!DOCTYPE html>
<html>
<body>
	<script>
        function asyncQueue(callback) {
            console.log("#2 We're inside asyncQueue-function.");
            // let's supose it takes 2000 milliseconds
            // for my turn to come
            setTimeout(() => {
                console.log("#3 After 2000 milliseconds. My turn comes, lets call a callback-function.");
                // after 2000 milliseconds
                // calling a callback function
                callback();
            }, 2000);
        }

        // suppose we are in a asynchronous queue
        // let's call an async-function to get a ticket
        console.log("#1 Call asyncQueue-function to get ticket.");
        asyncQueue(() => {
            console.log("#4 Callback called, It's time to buy a ticket :-)");
        });
        // we're passing a function using arrowFunction inside asyncQueue() method.
        // Learn more about arrowFunction in JavaScript ↓
    </script>
</body>
</html> 
Learn more about arrowFunction in JavaScript 👆

• Outcome-1 ↓

Open above HTML file in a Chrome Browser | Then do inspect and Open console.

#2 Promises
JavaScript built a mechanism in ES6 called a `promise`.
A promise is a placeholder for a future value. It serves the same function as callbacks does but has a clear syntax and makes it easier to handle errors.

Creating a Promise ↓
First we create an instance of a 'promise' by calling new keyword on the Promise class, see the code below:

var promise = new Promise((resolve, reject) => {

});
Let's Understand by breaking the code:
new Promise( pass-inner-function-here )
↑We pass an inner function to `Promise` class.
(resolve, reject) => { }
↑ Its an inner function, this inner-arrow-function takes two arguments `resolve` and `reject`.

We can also call these arguments anything other than resolve and reject, these are just name of an argument.
But actually these arguments are functions as an argument. Don't bother we'll understand that in depth ↓

Now, come inside of inner-function:
Inside the inner function 'we perform an asynchronous processing' and then when we are ready we call resolve().

Resolving a Promise ↓

We can get notified when a promise resolves by attaching a success/error handler to its then function, see the code below:
(This is just a glance↓ we'll understand code later by example)

// #2 create an anAsyncMethod()
// this method will return an object of `Promise`
anAsyncMethod() {
    let promise = new Promise((resolve, reject) => {
        // ...
        // here code come to resolve or reject promise
        
        // call this method to resolve promise, like this:
        resolve();
        
        // call this method to reject promise, like this:
        reject();
    });
    // return of a promise is required
    return promise;
}

// #1 calling an anAsyncMethod()
// over this method to its then function attaching a success/error handler arrow-functions
anAsyncMethod().then(
  () => console.log("Task Complete! Comes here after promise resolved"),
  () => console.log("Task Errored! Comes here after promise rejected"),
);
Look example below ↓ to understand more clearly

• Example-2 ↓

<!DOCTYPE html>
<html>
<body>
	<script>
        // let's set default value of error to false
        let error = false;

        function asyncQueue() {
            console.log("#2 We're inside asyncQueue-function.");
            // create an instance of a 'promise'
            var promise = new Promise((resolve, reject) => {
                // let's supose it takes 2000 milliseconds
                // for my turn to come
                setTimeout(() => {
                    console.log("Async Work Complete");
                    console.log("#3 After 2000 milliseconds. My turn comes.");
                    // after 2000 milliseconds
                    // calling a `reject` or `resolve` function
                    if (error) {
                        console.log("Call the reject() function, if an error in the async task.");
                        reject();
                    } else {
                        console.log("Call the resolve() function, if an async task completed without an error.");
                        resolve();
                    }
                }, 1000);
            });
            return promise;

        }

        // suppose we are in a asynchronous queue
        // let's call an async-function to get a ticket
        console.log("#1 Call asyncQueue-function to get ticket.");
        // get notified when a promise resolves by attaching a success/error handlers to its then function
        asyncQueue().then(
            ()  => {
                console.log("Success handler called - when task complete without error!");
                console.log("#4 It's time to buy a ticket :-)");
            },
            () => {
                console.log("Error handler called - when task has an error!");
            },
        );
    </script>
</body>
</html> 
Look below ↓ an output of the code

• Outcome-2 ↓

Click over this image👆 and look 👁 at the ‘console’ tab

#3 Async/Await
Async/Await is the extension of `promises`.
Adding a word `async` before any function means that function will always returns a promise.
`await` works only inside `async` functions, and `await` wait until the promise resolves and ready to return a result.

We'll understand quietly 'Async & Await' one by one – in #3.1 & #3.2 ↓

#3.1 Declare `Async` functions
Async function can be declared simply by adding async keyword before a function, see the code below:

async function myAsyncFunc() {
  return 123;
}

Now, it's required to call .then() over the function call to resolve this, see the code below:

• Example-3.1 ↓

<!DOCTYPE html>
<html>
<body>
	<script>

    	// `async` function | define a function start with `async` keyword
        async function myAsyncFunc() {
            // #1   `async` ensures that the function returns a promise,
            //      even without explicitly return
            //      return 123;

            // #2   we can also `explicitly` return a promise 
            //      this works same as above return
            return Promise.resolve(123);

            // we can do both the ways but
            // as `async` ensures that the function returns a promise
            // so why to write extra code to return explicitly
        }

		// calling a function - and to get return result call then()
		// the function inside then() will return the value 
        myAsyncFunc().then((returnVal) => {
            console.log(returnVal); // 123
        }); 

    </script>
</body>
</html> 
Look below ↓ an output of the code

• Outcome-3.1 ↓

Click over this image👆 and look 👁 at the 'console' tab

#3.2 Using `Await`
Another keyword await, that works only inside async functions. Await function is used to wait for the promise to resolve and it wait until the promise returns a result. Its job is to only wait async block.
"Using 'await' with 'async' function is like making a Synchronous function. Because await holds the code execution and wait for a 'Promise' to resolve - then only allow your next line of code to execute", see the code below:

• Example-3.2 ↓

<!DOCTYPE html>
<html>
<body>
	<script>

        // `async` function | define a function start with `async` keyword
        async function myAsyncFunc() {
            // #1  create a Promise (learn more about creating in step #2 Promises)
            console.log('#2 within a function creating a Promise.');
            let promise = new Promise((resolve, reject) => {
                // declare a setTimeout - to hold the code for 2000 milliseconds
                console.log('#3 inside promise setTimeout to wait for 2 seconds.');
                setTimeout(() => {
                    console.log('#5 calling resolve() function after 2 seconds.');
                    // resolve a promise after 2000 milliseconds
                    resolve("resolve done! 123");
                }, 2000);
            });

            console.log('#4 I am here to add `await` keyword before a promise.');
            console.log('...waiting time... 2 seconds...');
            // the next line of code can't be executed until the promise resolves
            // because we ↓ added `await` keyword before a promise
            let promiseResult = await promise; 

            console.log('#6 I couldn`t execute until promise resolves.');
            console.log('** If I called means promise is resolved.');

            // do alert to show the world that adding `await` keyword wait for `promise` to resolve
            alert(promiseResult); // "resolve done! 123"

            console.log('#7 Finally return promiseResult.');
            return promiseResult;
        }

        // calling a function - and to get return result call then()
		// the function inside then() will return the value
        console.log('#1 call an async function.');
        myAsyncFunc().then((returnVal) => {
            // I'll be called at the end of everything
            console.log('After waiting 2 seconds.. I get the promiseResult.');
            console.log('Result:', returnVal); // 123
        }); ; 

    </script>
</body>
</html> 
Copy and Paste this code in an HTML file and Open in browser to see the Magic :-)

• Outcome-3.2 ↓

Click over this image👆 and look 👁 at the 'console' tab

Done! 🤩 It’s that simple to understand the concept of 'Promises | Async/Await'.

See you later 👋👋


Feel free to comment down in the comment box… If I missed anything or anything is incorrect or anything does not works for you :)
Stay connected for more articles.

Next, Learn to Use Async-Pipe to manage Observable Subscriptions and Prevent Memory Leaks.

Angular: Use Async-Pipe to manage Observable Subscriptions and Prevent Memory Leaks.
Async-Pipe is an Angular built in tool to manage Observable-Subscriptions. Wecan easily simplify functionality of an Angular code using the async pipe. Let’slearn to use Async-Pipe | Observable-Subscriptions. Async-Pipe manages Observable-Subscriptions, Observables are the type ofvariables whose…