2016/02/12

Avoiding Callback Hell - the simple way

Callback hell is one of the big issues with nodejs but here I explain how you can deal with it in a not so painfull approach.

Just use the same callback function always and control flows with flags. The only drawback is that you have to get arguments by position because names would not make sense.
It is not "elegant" but it is easier to read than promises and other async frameworks in my opinion.


var flow1 = new Flow1(
 {
  execute_next_step: function(err) {
   if (err) {
    console.log(err);
   };
  }
 }
);

flow1.execute_next_step();

function Flow1(parent_flow) {
 this.execute_next_step = function(err) {
  if (err) return parent_flow.execute_next_step(err);
  if (!this.next_step) this.next_step = 'START';
  console.log('Flow1:', this.next_step);
  switch (this.next_step) {
   case 'START':
    this.next_step = 'FIRST_ASYNC_TASK_FINISHED';
    firstAsyncTask(this.execute_next_step.bind(this));
    break;
   case 'FIRST_ASYNC_TASK_FINISHED':
    this.firstAsyncTaskReturn = arguments[1];
    this.next_step = 'ANOTHER_FLOW_FINISHED';
    this.another_flow = new AnotherFlow(this);
    this.another_flow.execute_next_step();
    break;
   case 'ANOTHER_FLOW_FINISHED':
    this.another_flow_return = arguments[1];
    this.next_step = 'FINISH';
    this.execute_next_step();
    break;
   case 'FINISH':
    parent_flow.execute_next_step();
    break;
  }
 }
}

function AnotherFlow(parent_flow) {
 this.execute_next_step = function(err) {
  if (err) return parent_flow.execute_next_step(err);
  if (!this.next_step) this.next_step = 'START';
  console.log('AnotherFlow:', this.next_step);
  switch (this.next_step) {
   case 'START':
    console.log('I dont want to do anything!. Calling parent');
    parent_flow.execute_next_step();
    break;
  }
 }
}