I'm trying to call an asynchronous function (the 'child') from within another asynchronous function (the 'parent'). To make things complicated, the parent function exposes a dual API (callback + promise). This is done using the Q library's defer() and nodeify(), like so:
var parent = function(p_arg, callback) {
  var deferred = Q.defer();
  child(arg, function(err, cb_arg) {
    if(err)
      deferred.reject(err);
    else
      deferred.resolve(cb_arg);
  });
  //If a callback was supplied, register it using nodeify(). Otherwise, return a promise.
  if(callback)
    deferred.promise.nodeify(callback);
  else
    return deferred.promise;
}
Note that the child function doesn't return a promise. Now depending on the value of the argument passed to the child's callback (cb_arg), I might decide to make a fresh call to parent, albeit with a modified argument (p_arg). How do I do this keeping in mind the dual nature of the parent's API?
This is what I've been able to come up with so far:
child(arg, function(err, cb_arg) {
  if(err)
    deferred.reject(err);
  else if(cb_arg.condition) {
    /*Make a fresh call to parent, passing in a modified p_arg*/
    if(callback)
      parent(p_arg + 1, callback);
    else
      deferred.promise = parent(p_arg + 1);
      /*
        ^ Is this the correct way to do this?
        My goal is to return the promise returned by the fresh parent() call,
        so how about I just assign it to the current parent() call's deferred.promise?
      */
  } 
  else
    deferred.resolve(cb_arg);
});
UPDATE: Okay, I just had a moment of clarity regarding this problem. I now think that what actually needs to be done is the following:
child(arg, function(err, cb_arg) {
  if(err)
    deferred.reject(err);
  else if(cb_arg.condition) {
    /*Make a fresh call to parent, passing in a modified p_arg*/
    if(callback)
      parent(p_arg + 1, callback);
    else
      parent(p_arg + 1)
      .then(function(p_ret) {
          deferred.resolve(p_ret);
      }, function(p_err) {
          deferred.reject(p_err);
      });
  } 
  else
    deferred.resolve(cb_arg);
});
This pattern seems to work for my particular use case. But do let me know in case there are any glaring async-related errors with this approach.
 
     
    