1

@lyjackal helped me here (NodeJS Asynchronous and Recursive) to solve recursive for finding children.

I am still trying to get my head around nodejs promises. I have a similar problem as the previous post, but slightly different. I feel this code is close, but it doesn't work.

I have an Assignment, and Assignment has a reference to a Path. That Path, and all paths, may or may not have a parent Path. I need this code, to find the path of paths as it were, and just stack a few attributes of each path in an array. The array at the end would look like this:

[ [0]=>{field: name, match: match_type, value:value},
  [1]=>{field: name, match: match_type, value:value},
  ...]

The order of the array doesn't even matter. Here is the code with Promises... that is broken:

exports.assignRecursiveQuery = function(req,res) {
    var methods = {}
    var query_to_save = []

    methods.recursiveParents = function(path) {
        return new Promise(function(resolve, reject) {
          Path.find({
            _id: path.parent
          }).exec(function(err, parentPaths) {
            Promise
              .all(parentPaths.map(function(parentPath) {
                return methods.recursiveParents(parentPath) 
              }))
              .then(function(promisedPaths) {
                return resolve(promisedPaths);
              });
          });
        });
      }

    Path.find({_id: req.assignment.path_end}).exec(function(err,lastPaths) {
        //add first query rule
        console.log(lastPaths[0]);
        query_to_save.push({field:lastPaths[0].field.api,match:lastPaths[0].match,value:lastPaths[0].value})

        Promise.all(lastPaths.map(function(path) {
          return methods.recursiveParents(path);
        })).then(function(resolvedPaths) {
            for( var x=0; x<resolvedPaths.length; x++ ) {
                console.log(resolvedPaths[x])
                query_to_save.push({field:resolvedPaths[x].field.api,match:resolvedPaths[x].match,value:resolvedPaths[x].value});
            }
            console.log(query_to_save);
            res.jsonp(req.assignment)
        });
    });
}
Community
  • 1
  • 1
sol
  • 135
  • 9
  • Have you unit tested `methods.recursiveParents()`? – Roamer-1888 Aug 18 '15 at 22:40
  • Try [not to use the `Promise` constructor](http://stackoverflow.com/q/23803743/1048572) except for immediate (lowest-level) promisification. – Bergi Aug 18 '15 at 23:35
  • @Bergi I get an array at the end that looks like this: [ [ [ [] ] ] ] for a 4-level parent/child relationship. No attributes from the query_to_save.push() shown in the array. – sol Aug 19 '15 at 03:30
  • @Roamer-1888 I have not. – sol Aug 19 '15 at 03:30
  • @sol: Well that's what your code does. It does recurse (and nest arrays) until `Path.find` yields an empty array. It never fills them with anything, the base case returns nothing but an empty array. What did you expect? how did you plan it to work? – Bergi Aug 19 '15 at 08:53
  • @bergi what I *wanted* it to do was collect a promise with a result for each nested parent path then return them all to the original request with the "Then" (right about the console.log), and loop through the results and add them to query_to_save variable. I've been developing in php for years, and this year have picked up python and node. I get my head around concepts quickly, but I'm not a daily developer by trade, so it takes me a little longer to put them into practice and have them work :) thanks for your help. Asynchronous as an example is a new paradigm :) – sol Aug 20 '15 at 20:29
  • @sol: And that's exactly what you are doing. Only your "results" are *arrays*. This has nothing to do with being asynchronous, your recursion wouldn't work even if it was written synchronously. But maybe that would help us to identify what you actually want - try to write it as if was synchronous and show us that. – Bergi Aug 20 '15 at 20:37

1 Answers1

0

I got it to work as desired with the following code, not sure if it is the "right way" but it does work as expected.

exports.assignRecursiveQuery = function(req, res, next) {
  var query_to_save = []

  var methods = {};

  methods.recursiveChildren = function(path) {
    var item_to_save = {
     field: path.field.api,
     match: path.match,
     value: path.value
    }
    query_to_save.push(item_to_save);

    return new Promise(function(resolve, reject) {
      Path.find({_id: path.parent}).exec(function(err, parentPath) {
        Promise
          .all(parentPath.map(function(parent) {
            /* collect a promise for each child path this returns a promise */
            return methods.recursiveChildren(parent);
          }))
          .then(function(resolvedPaths) {
             /* the top level promise */
            resolve();
          });
      });
   });
  }

  Path.find({_id:req.assignment.path_end}).exec(function(err, paths) {
    Promise.all(paths.map(function(path) {
      return methods.recursiveChildren(path);
    })).then(function(resolvedPaths) {
  var assignment = req.assignment;
     assignment.assign_query = query_to_save;
     assignment.save(function(err) {
   if (err) {
    return res.status(400).send({
     message: errorHandler.getErrorMessage(err)
    });
   } else {
    req.assignment = assignment;
    next();
   }
     });
   });
  });
};
sol
  • 135
  • 9