0

I used Q library to server side (nodejs) to avoid the callback pyramid.

The callback pyramid is as below :

var isNext = <any boolean>;
db.model1.find({a: val}).exec().
then(function(err, res){
if( res && isNext){
  db.model2.find({b: val}).exec().then(function(err, res){ 
      callback();
  });
}else{
  callback();
}
});

I used q library to avoid the callback pyramid like this :

var isNext = <any boolean>;
q.nfcall(find1(id))
    .then( function( MODEL1 ){
        var deferred = q.defer();
        if( MODEL1 && isNext){
            deferred.promise = find2( id );
        }else{
            deferred.resolve(MODEL1);
        }
        return deferred.promise;
    })
    .fail(function(err){
        console.log('--> err : ' + JSON.stringify(err));
    })
    .done(function(){
        console.log('update done..');
       // main callback
    });

and find1 and find2 functions are as :

function find1(id){
var deferred = q.defer();
db.model1.findOne({_id: id}).exec()
    .then(function(model){
        if( model ){
            // some operation
            deferred.resolve( model );
        }else{
            deferred.reject( 'error' );
        }
    },function(err){
        deferred.reject( err );
    }
);
return deferred.promise;
}

function find2(id){
var deferred = q.defer();
db.model2.findOne({_id: id}).exec()
    .then(function(model){
        if( model ){
            // some operation
            deferred.resolve( model );
        }else{
            deferred.reject( 'error' );
        }
    },function(err){
        deferred.reject( err );
    }
);
return deferred.promise;
}

So, the problem with this is, the .then part, when Q library is used, is not getting executed . In this problem, the call is always going into the .fail part of the execution. What I am expecting is the execution should go inside the .then part when find1() call is executed.

kv89
  • 13
  • 6
  • What `err` do you get? And what is this `//some ooperation` in your find functions? – Bergi Dec 16 '15 at 11:37
  • The //some operation is the business logic that is required. The error is coming as empty JSON as the call to .fail is getting executed even if the find1() is not returning any error. – kv89 Dec 16 '15 at 12:27

1 Answers1

2

Your find1 function already is returning a promise - you should not must not use it with Q.nfcall.

Just do

var isNext = <any boolean>;
find1(id)
.then(function(MODEL1) {
    if (MODEL1 && isNext) {
        return find2(id);
    } else {
        return MODEL1; // you can just return plain values as well, btw
    }
})
.fail(function(err) {
    console.log('--> err : ' + JSON.stringify(err));
})
.done(function() {
    console.log('update done..');
    // main callback
});

Notice that you should avoid the deferred antipattern. Those exec invocations already return promises, so all you might want to do is cast them to Q promises and reject on falsy results.

function find1(id) {
    return q(db.model1.findOne({_id: id}).exec())
    .then(function(model) {
        if (model) {
            // some operation
            return model;
        } else {
            throw new Error('error');
        }
    });
}
function find2(id) {
    // analogous
}
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    I think that you can even set the promise library on Mongoose (is this mongoose?) globally and avoid the `q`s around stuff. – Benjamin Gruenbaum Dec 16 '15 at 11:56
  • It worked after removing the q.nfcall on find1 method. Thanks [Bergi](http://stackoverflow.com/users/1048572/bergi) – kv89 Dec 16 '15 at 12:38