Asynchronous response - from callbacks to promises

Sometimes, we might need to build functionalities that depend on time as a parameter of something, and we need to introduce code patterns that handle this deferred change in the application state.

For all these scenarios, we have always used code patterns, such as the callback pattern, where the function that triggers the asynchronous action expects another function in its signature, which will emit a sort of notification as soon as the asynchronous operation is completed, as follows:

function notifyCompletion() {
console.log('Our asynchronous operation has been completed');
}

function asynchronousOperation(callback) {
setTimeout(() => {
callback();
}, 5000);
}

asynchronousOperation(notifyCompletion);

The problem with this pattern is that code can become quite confusing and cumbersome as the application grows and more and more nested callbacks are introduced. In order to avoid this scenario, Promises introduced a new way of envisioning asynchronous data management by conforming to a neater and more solid interface, in which different asynchronous operations can be chained at the same level and even be split and returned from other functions. The following code introduces how to construct a Promise:

function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(42);
}, 3000);
})
}

getData().then((data) => console.log('Data',data)) // 42

The preceding code example is perhaps a bit more verbose, but it definitely produces a more expressive and elegant interface for our function. As for chaining data, we need to understand what problem we are solving. We are solving something called callback hell, looking like this:

getData(function(data){
getMoreData(data, function(moreData){
getEvenMoreData(moreData, function(evenMoreData) {
// done here
});
});
});

As can be seen in the preceding code, we have a situation where we are dependent on the previous async call and the data it brings back before we are able to do the next async call. This leads to us having to execute a method inside of a callback inside of a callback, and so on and so forth. You get the idea—the code quickly ends up looking horrible, also known as callback hell. Continuing with the subject of chaining async calls, chaining is the answer to callback hell and Promises allows us to chain them, like so:

getData()
.then(getMoreData)
.then(getEvenMoreData);

function getData() {
return new Promise(resolve) => resolve('data');
}

function getMoreData(data) {
return new Promise((resolve, reject) => resolve('more data'));
}

function getEvenMoreData(data) {
return new Promise((resolve, reject) => resolve('even more data'));
}

The chaining of the .then() method calls in the preceding code shows how we can clearly line up one async call after another, and that the previous async call has input its result in the upcoming async method.

So, Promises take over the coding arena by storm and no developer out there seems to question the great value they bring to the game. So, why do we need another paradigm? Well, because sometimes we might need to produce a response output that follows a more complex digest process as it is being returned, or even cancel the whole process. This cannot be done with Promises, because they are triggered as soon as they're being instantiated. In other words, Promises are not lazy. On the other hand, the possibility of tearing down an asynchronous operation after it has been fired but not completed yet can become quite handy in certain scenarios. Promises only allow us to resolve or reject an asynchronous operation, but sometimes we might want to abort everything before getting to that point. On top of that, Promises behave as one-time operations. Once they are resolved, we cannot expect to receive any further information or state change notification unless we run everything again from scratch. Moreover, we sometimes need a more proactive implementation of async data handling. This is where Observables come into the game. To summarize the limitations of promises:

  • They cannot be cancelled
  • They are  immediately executed
  • They are one-time operations only; there is no easy way to retry them
  • They respond with only one value
..................Content has been hidden....................

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