Nodejs & Promise : advanced tips – part one – Anti-pattern

Here is the first part of a two parts-post dedicated to promise. This part is about some anti-patterns that we ofen use when we begin to play with promise. The second part explains how writing code able to use any promise implementation.


♻ Promise hell

While promise are made to avoid callbak hell, it still possible to see such code:

'use strict';

function doSomethingAsync1() { return Promise.resolve(); }
function doSomethingAsync2() { return Promise.resolve(); }
function doSomethingAsync3() { return Promise.resolve(); }
function doSomethingAsync4() { return Promise.resolve(); }

doSomethingAsync1().then((result1)=>{
  return doSomethingAsync2(result1).then((result2) => {
    return doSomethingAsync3(result2).then((result3)=> {
      return doSomethingAsync4(result3).then((result4) => {
        console.log(result4);
      });
    });
  });
}, (err) => {
  console.log(err);
});

Each result variable is accessible from inner code and thus is error prone, while with promise it’s easy to avoid this:

'use strict';

doSomethingAsync1().then((result)=> {
  return doSomethingAsync2(result);
}).then((result) => {
  return doSomethingAsync3(result);
}).then((result) => {
  return doSomethingAsync4(result);
}).then((result) => { 
  console.log(result); 
},(err) => { 
  console.log(err); 
});

With the ‘short arrow notation’ these becomes:

'use strict';

doSomethingAsync1().then(result => 
  doSomethingAsync2(result)
).then(result => {
  doSomethingAsync3(result)
}).then(result => {
  doSomethingAsync4(result)
}).then(result => { 
  console.log(result); 
},(err) => { 
  console.log(err); 
});

♻ Partial error management

Can you say if one of this two codes is better ?

const somethingAsync = Promise.resolve('foo');
somethingAsync.then( 
  (result) => { 
    // Processing result 
   }, (err) => { 
   // error management 
   });
somethingAsync
  .then((result) => {
    // Processing result
  })
  .catch((err) => { 
    // error management 
  });

The first code handle ‘somethingAsync’ errors only. It does nothing if  ‘Processing result’ failed because the error handler passed in ‘then’ covers only the promise returns by aysnc code.

The second code handle both ‘somethingAsync’ and ‘Processing result’ errors, thanks to promise chaining. If proccesing result throws an error, ‘then’ returns a rejected promise and therefore catch is called. Thus the code snippet at the end of the previous chapter is better like this:

doSomethingAsync1()
.then(result => 
  doSomethingAsync2(result)
).then(result => {
  doSomethingAsync3(result)
}).then(result => {
  doSomethingAsync4(result)
}).then(result => { 
  console.log(result); 
}).catch((err) => { 
  console.log(err); 
});

Bluebirdjs’ wiki has another way of explaining this.

♻ Error is not reject

A function can have a synchronous action to do before calling an asynchronous function:

function foo() {
  let result = doSomethingSync();
  return doSomethingAsync(result);
}

Such code has a huge pitfall. Typically one will use it this like:

foo().then(....);

What’s wrong with this ?
If the synchronous code throw an error, nothing can catch it…

A safer approach consist of writing async function so that all errors are delivered through a promise rejection. Here is a better exemple:

  function foo() {
    try {
      let result = doSomethingSync();
      return doSomethingAsync(result);
    } catch (err) {
      return Promise.reject(err);
    }
  }
}

I’m a fan of  bluebirdjs, which offer a mean to easily turn  an error into a rejection:

const Promise = require('bluebird');

function foo() {
  return Promise.try(() => {
    let result = doSomethingSync();
    return doSomethingAsync(result);
  });
}

This concludes this post. If you don’t know bluebirdjs yet I advise you to have look at it, as far as I know it’s the best promise implementation in Node world (let me know if there’s lib that can compet with). My next post about promise will be issued in a couple of weeks.

See you and have a nice code 🙋

Advertisements

One thought on “Nodejs & Promise : advanced tips – part one – Anti-pattern

  1. Pingback: Nodejs & Promise : advanced tips – part two – Using Promise ? Yes, but just any one ;-) – yatatb

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s