1

I am currently trying to refactor the codebase that I have and want to have a more developer friendly codebase. Part 1 of that is changing callback to Promises. Currently, at some places we are using Async.waterfall to flatten the callback hell, which works for me. The remaining places where we couldn't was because they were conditional callbacks, That means different callback function inside if and else

if(x){
    call_this_callback()
}else{
    call_other_callback()
}

Now I use bluebird for promises in Node.JS and I can't figure out how to handle conditional callback to flatten the callback hell.

EDIT A more realistic scenario, considering I didn't get the crux of the issue.

var promise = Collection1.find({
    condn: true
}).exec()
promise.then(function(val) {
    if(val){
        return gotoStep2();
    }else{
        return createItem();
    }
})
.then(function (res){
    //I don't know which response I am getting Is it the promise of gotoStep2
    //or from the createItem because in both the different database is going
    //to be called. How do I handle this
})
Saras Arya
  • 3,022
  • 8
  • 41
  • 71

2 Answers2

2

There is no magic, you can easily chain promises with return inside a promise.

var promise = Collection1.find({
    condn: true
}).exec();

//first approach
promise.then(function(val) {
    if(val){
        return gotoStep2()
          .then(function(result) {
            //handle result from gotoStep2() here
          });
    }else{
        return createItem()
          .then(function(result) {
            //handle result from createItem() here
          });
    }
});

//second approach
promise.then(function(val) {
    return new Promise(function() {
        if(val){
            return gotoStep2()
        } else {
            return createItem();
        }
    }).then(function(result) {
        if (val) {
            //this is result from gotoStep2();
        } else {
            //this is result from createItem();
        }
    });
});

//third approach
promise.then(function(val) {
    if(val){
        return gotoStep2(); //assume return array
    } else {
        return createItem(); //assume return object
    }
}).then(function(result) {
    //validate the result if it has own status or type
    if (Array.isArray(result)) {
        //returned from gotoStep2()
    } else {
        //returned from createItem()
    }
    //you can have other validation or status checking based on your results
});

Edit: Update sample code because author updated his sample code. Edit: Added 3rd approach to help you understand promise chain

iKoala
  • 870
  • 4
  • 11
  • here you are using three return calls..which will be called ? – arjun kori Nov 30 '16 at 07:58
  • I just edited the question. Made the scenario more explanatory, could you edit your answer to reflect that. – Saras Arya Nov 30 '16 at 08:02
  • The first approach I find is discouraging as it promotes callbacks within a callback, which I don't want. The second one is a more generic approach, requiring the use of closure, where I need to make sure that I have different variables in all the consecutive chaining function.The third one is suitable when you have different datatype from two different functions. None of them seems to be generic enough but will do at this point of time. Will continue to hunt for more elegant solutions. If found will update it. Thanks for your time. Much appreciated. – Saras Arya Nov 30 '16 at 09:07
  • In method 1 if you have `if inside if inside if`. It would defeat the promises, which are seen to as a solution of callback hell. – Saras Arya Nov 30 '16 at 09:10
  • Now I have a question which I don't understand. If you want to distinct the returned result from `gotoStep2` and `createItem`, I can assume that you have different logic to handle the results. In the 1st approach, it separate and chain up the the logic to handle the results from different functions. I think you misunderstand a point, Promise doesn't solve the callback hell, in only solves the situation where code marches to the right faster than it marches forward, i.e. enhance code readability. – iKoala Nov 30 '16 at 09:16
  • I agree you shouldn't place too many `if .. else ..` case in the same code block. Instead, should you just place a function handler which only serve the results from `gotoStep2` and `createItem`? I didn't mean you should accept my answer, but I think what you expect is a bit interesting so I just want to see if I can learn something from your perspective. – iKoala Nov 30 '16 at 09:19
0

Here is the answer to the promise branch: nested and unnested. Make the branches and don't join them together.

Community
  • 1
  • 1
jiajianrong
  • 868
  • 8
  • 24
  • It's a long answer and question. @jiajianrong I'll have a look on the implementation and get back to you tomorrow on this. – Saras Arya Nov 30 '16 at 12:03