← Back

Manage and Promisify async actions in javascript

Javascript is different from other languages. Programmers from other languages once entering the javascript era might get confused easily but the action is not true on the reverse side. One of the easy to get yet hard to implement and maintain task in Javascript is to perform an async task. To asynchronously run a task in Javascript, Developers have 3 different options.

  1. Callbacks (ES5)
  2. Promises (ES6)
  3. Async / Await (ES7: still draft)

In this article we are going to cover the first 2 options yet leaving the third one to the audience, probably lots of snippets and great articles could be found about it around the internet.

Asynchronous Task

An asynchronous task is a task that’s not going to return value as soon as it’s called, the timestamp between calling the async task and returning the value is unknown and dependant to many factors.

Callback

To control the returning value from our async task and working with it, our first and the hardest to maintain and chain, would be callbacks. Callbacks are first class functions passed to the async function as an argument. Let’s assume our async function is just a setTimeout that returns a random integer.

function myAsyncTask() {
  setTimeout(function() {
   return Math.random()
  }, 1000)
}

And also assume that we are going to control the returned value by multiplying by 2.

function controller(input) {
  alert(input)
}

To pass controller to the async function, it should accept an argument:

function myAsyncTask(callback) {
  setTimeout(function() {
    callback(Math.random())
  }, 1000)
}

Now we pass the controller to the async function to see what happens!

myAsyncTask(controller)

This will alert double of the random input after 1 seconds. Give it a try! As you see, callbacks are nice BUT, what if we wanna do multiple async tasks altogether? what if we wanna share code snippets and function in nested callback calls? Nested callbacks are typically HELL. I mean it. In fact they are so hard to maintain that in Node JS, since all tasks are asynchronous, the tasks should be called nested and you’ll simply end up with multiple (easily up to 5 steps) nested callbacks inside each other. This problem led the dev community into requesting other tools to manage these kind of functions and the tool was called PROMISE.

Promise

Promise came to make dev lives easier. promises are often hard to understand. Once I saw above infographic about a weather forecast example and how it can be converted to promise concept (originally from Andy Shora Blog), I finally grasped the concept.

Promises are like, hey code snippet, promise me to do this async task, if your returned value fulfills this condition, resolve the value else reject it.

Every promise has a resolve and reject function that are relatively success and error of task. Promises are like try-catch` blocks. You could chain promises infinite times but pass the errors down to the single bottom catch. The resolve function is used inside a .thenmethod and the reject in .catch Let’s rewrite our fake async task in promise manner!

function myAsyncTask() {
  return new Promise(function(resolve, reject) {
   setTimeout(function() {
    var rand = Math.random()
    if (rand > 0.5) resolve(rand)
    else reject(rand)
   }, 1000)
  })
 }
function resolveController(input) {
  alert('Value greater than 0.5 is :' + input)
}
function rejectController(input) {
  alert('Value less that 0.5 is : ' + input)
}

Now since the resolve function is resolveController and reject function is rejectController, use resolveController inside .then and rejectController inside .catch.

myAsyncTask().then(resolveController).catch(rejectController)

The code is now better read, better understood and much easier to chain and maintain.

Last Attack

As appeared in title of this article, promisify is the process of converting a callback based procedure into promise. It’s actually simple and useful for some reasons.

  1. It’s luxury :-P
  2. It’s modern javascript and more up-to-dated 3.It’s better to read and look at
  3. Many async tasks such as reading and writing to fileSystem, Ajax request, Connecting to and querying on database,… are present inside a real world javascript application and you gotta get out from the callback hell ASAP

So how do we convert a callback hell to a promise paradise? It’s freakingly easy. Just parallel convert success callbacks and error callbacks into resolve and reject respectively.

Consider below jQuery ajax request:

function getDataFromServer(url, success, fail) {
  return $.getJson(url, success, fail)
}
function getUsersByCallback() {
  return getDataFromServer('https://myrestapi.com/users',function(response) {
   console.log('Yesss, I got users')
  },function(error) {
   console.error('Bummer, could not get users right now')
  })
 }

Once converted into promise, would look like:

function getDataFromServer(url) {
  return new Promise(function(resolve, reject) {
   $.getJson(url, function(response)      {resolve(response)},function(error) {reject(error)})
  })
 }
 function getUsersByPromise() {
 getDataFromServer('https://myrestapi.com/users').then(function(response) {
   console.log('Yesss, I got users')
  }).catch((error) {
   console.error('Bummer, could not get users right now')
  })
 }

That easy!!!!

Conclusion

Async tasks are everywhere even outside of javascript and every language provides stable methods and tools to deal with them. In javascript callbacks, promises and async/awaits are available as solutions. As you saw, async/await is still a draft but has been implemented in recent versions of Babel transpiler so you could give it a try but don’t get used to it to much as it could vanish like in seconds.

Promisify your async tasks with the technique discussed in the article and you’re good to go further than working inside a callback hell.

← Cross-Domain Iframe-parent communication Hide browsers's default metadata when printing a webpage →
More about me