2

Say I have the following in thing.js:

var db = require('my-database-module');

module.exports = class Thing() {
  constructor(id, parentId, name) {
    this.id = id;
    this.parentId = parentId;
    this.name = name;
  }

  static find(id) {
    // NOTE: The following find() function returns a Promise.
    return db.collection('things').find(id);
  }

  parent() {
    return this.constructor.find(this.parentId);
  }
}

Normally finding Things would be accomplished with the following:

var Thing = require('thing');

Thing.find(123).then(function(thing) {
  // Do something with `thing`
});

You'll notice that I'm wanting to implement a parent/child hierarchy. I would like to add an ancestors function that returns an array of ancestor Thing objects for a given instance of Thing:

module.exports = class Thing() {

  // ...

  ancestors() {
    var a = []

    // Can't figure this out...

    return a;
  }
}

Because the Thing#parent function returns a Promise, I'm getting confused on how the ancestors function should work. It would need to recursively lookup successive parents of the Thing instance.

I've seen the Array.prototype.reduce function can be used for chaining Promises, but I don't know the Promises to chain upfront since it needs to recursively look for the parent, grandparent, great grandparent, etc.

Any ideas on how to structure this function?

robertwbradford
  • 6,181
  • 9
  • 36
  • 61
  • Have a look at [this example approach to implement a `while` loop](http://stackoverflow.com/a/29396005/1048572) – Bergi Mar 08 '16 at 23:05

1 Answers1

1

If the method .parent() returns a promise who's fulfilled value would be the parent and it returns null when there are no more parents, then you can write something like this:

ancestors() {
    var parents = [];

    function getNext(obj) {
        return obj.parent().then(function(parent) {
            if (!parent) {
                // if no more parents, then we must be done with the chain
                // so return the whole parent chain
                return parents;
            } else {
                // still got another parent, add to the array and keep going
                parents.push(parent);
                // returning another promise here chains it to the previous one
                return getNext(parent);
            }
        });
    }

    return getNext(this);
}

// usage
obj.ancestors().then(function(parents) {
    // access to the whole parents array here
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979