DEV Community

Samira Awad
Samira Awad

Posted on

Promises vs Callbacks.

The first thing is: What are promises and callbacks?

In short, promises are JavaScript objects that can be handled with both the ‘.then’ and ‘.catch’ methods, as well as ‘async-await’. On the other hand, callbacks are functions that are passed as a parameter to another function, so that they can be handled by it.
But what are they used for and when is it better to choose a callback or a promise?

BEFORE CALLBACKS:
In a synchronous function, the program executes the requests in order. If the code needs to query a third party (database, API, etc.), this may take time (seconds or milliseconds). In a synchronous program, the code does not wait for the response to arrive before continuing execution, which can result in a lack of response if not handled correctly. For this, asynchrony was created.

By creating asynchronous code in JavaScript, asynchronous functions can be executed and their result returned once the asynchronous task has finished. To do this, the JavaScript code is constantly listening and monitoring to verify if the asynchronous task has been resolved.
However, this continuous monitoring work can be avoided by using callbacks. This way, the code returns the result once the asynchronous task has finished. A callback waits for the response from the asynchronous task and returns it once it has finished.

Additionally, JavaScript can do only one thing at a time since it has only one thread of execution. If there is an asynchronous task, it is skipped and continues with the following tasks until the task has finished executing and JavaScript returns the response of that piece of code. However, there was no control over when we want this response to be returned. For this, callbacks were created.

CALLBACKS:
A callback is a function that is passed as a parameter to a function, with the purpose of being called and executed after the asynchronous task inside. However, we only have control of the response within this function. That is, callbacks need another function to receive them, where all control of the response is only contained in this function.

Additionally, callbacks have a well-known term called ‘callbackhell’, which refers to when we have many calls to nested callbacks. This results in code that is difficult to predict, confusing, and prone to errors.
In order to have control in any part of the code, promises were created. This way, you don’t need a function to execute the asynchronous piece of code along with the callback.

PROMISES:
They are an evolution of callbacks, which work just like promises in real life. They have the advantage over callbacks that, when initialized, they immediately return a value: a Promise object. This occurs even before the asynchronous task is finished.

The Promise object is the representation of a future value, with the promise that it may or may not complete successfully, but will always return a value.

Another advantage of a promise over a callback is that its returned result can be used in any part of the code that we deem appropriate. For example, we can use it only in certain conditional scenarios, using if-else blocks.

An example of a promise is a redemption ticket for a hamburger. If I go to a restaurant and pay for a redemption ticket for a hamburger, they promise me that when I use it, they will give me a hamburger. So, I can do whatever I want with my time and whenever I see fit, I go to the restaurant and redeem my ticket to receive the promised burger. In that case, if the chef manages to complete the task (cook the burger), I receive my burger. Otherwise, if something goes wrong, I will receive a message or my money back.

To create a promise, we must first initialize it as NEW promise. This promise takes two functions as parameters, ‘resolve()’ and ‘reject()’. We will use these functions within the promise: we return resolve() if the request has been made successfully, and we return reject() if an error occurred. Within both functions, we define, using an anonymous function (arrow), the response that we want to return for those cases.

As a good practice, it is advisable to first define the errors with ‘reject’, and then define the resolved response with a ‘resolve’.

Image description

THEN-CATCH vs ASYNC-AWAIT:
There are two ways to handle promise responses. The first is with the then and catch methods, the second is with the async-await functions.

THEN-CATCH:
To handle the response of a promise that has been positively resolved, when calling the promise, we use the ‘.then()’ method. Within the method, the response successfully returned from the promise is received as a parameter and, with an anonymous function (arrow), we can do whatever we deem appropriate with this response. That is, ‘.then’ collects the response that was defined in the ‘resolve()’ function.

After the ‘.then’ method, we must use the ‘.catch()’ method to handle the possible rejected or failed response of the promise. Within the method, the returned response is received as a parameter, which would be the error returned and, with an anonymous function (arrow), we can do what we deem appropriate with this response. That is, ‘.catch’ receives the error response that we defined in our ‘reject()’ function.

Example:

Image description

ASYNC- AWAIT:
This way of handling promises allows us to have more sequential and orderly code. This is because we wrap the promise inside an asynchronous function, and we can, within the same function, return its response and save it in a variable by prefixing the call of the promise with an ‘await’.

The word ‘await’ will cause the function to wait for the promise response before continuing to execute code. You can have several ‘await’ tasks within the same asynchronous function.

The decision of which one to use is up to each programmer; However, with ‘async-await’ we can call the asynchronous function that contains the promise wherever we deem appropriate, without having to write the promise handlers again (as happens in the case of then-catch). Just by invoking the asynchronous function, we will obtain the result of the promise.

Furthermore, we can do whatever we want in the function, once the response is obtained, before returning it, maintaining a sequential and orderly order. It is important to indicate how possible errors returned from the promise should be handled. To do this, we wrap the promise call in a ‘try’, and we wrap the error handling in a ‘catch’.

Example:

Image description

FETCH AND AXIOS:
They are asynchronous functions of JavaScript libraries that allow us to make requests to third parties to perform tasks, such as queries to APIs, among others.

These functions implicitly work with promises and return them. To access the response of this promise, we must follow their call with the ‘then-catch’ methods or use the ‘async-await’ functions.

Top comments (0)