1

I've read Produce a promise which depends on recursive promises chaining recursive promise with bluebird Recursive Promises? but I still can't figure out what's wrong with how I'm structuring my promises

So I'm fetching objects from a database. Every object has a field, but sometimes it has a reference to a UUID. So for example, if a person has a friend and mother, it would be like

{
   "id": e872530a-27fc-4263-ad39-9a21568c31ef,
   "name": "dood",
   "friendId": "571746fc-686d-4170-a53e-7b7daca62fa0",
   "motherId": "99b65849-1f1c-4881-a1d0-c5ae432e83a2"
}

Now, the idea is when I fetch an object I want to replace any other UUID's with the expanded version.

{
   "id": e872530a-27fc-4263-ad39-9a21568c31ef,
   "name": "dood",
   "friendId": {
      "id": "571746fc-686d-4170-a53e-7b7daca62fa0",
      "name": "peter"
   },
   "motherId": {
      "id": "99b65849-1f1c-4881-a1d0-c5ae432e83a2",
      "name": "ma"
   }
}

Thus, I'm using promises and recursion to try this but I can't figure out what's going wrong in my promises. I get this result instead

{
   "id": e872530a-27fc-4263-ad39-9a21568c31ef,
   "name": "dood",
   "friendId": {
      "isFulfilled": False,
      "isRejected": False
   },
   "motherId": {
      "isFulfilled": False,
      "isRejected": False
   }
}

I've using bluebird js, and here is how the code looks like

function getExpandedObj(uuid, recursiveLevel) {
    return getObj(uuid) //This gets the object from the database
        .then(function(obj) {
           //I convert the obj to an array where each element is
           //{property:value} so I can do a map over it
           // some code to do that, I think it's irrelevant so I'll 
           // skip it
           return objArr;
        })
        .map(function(obj) {
            //prevent infinite recursion
            if (recursiveLevel > 0) {
               for (var property in obj) {
                   if (typeof(obj[property]) === "string" ) {
                       var uuid = obj[property].match(/(\w{8}(-\w{4}){3}-\w{12}?)/g);
                       if (uuid != null) {
                          uuid = uuid[0];
                          obj[property] = getExpandedObj(uuid, recursiveLevel-1)
                              .then(function(exObj) { return exObj;})
                       }
                   }
               }
            }
        })
        .then(function(obj) {return obj;})
}  
Community
  • 1
  • 1
Gakho
  • 603
  • 1
  • 9
  • 18
  • Ah, so that is what [you were asking for previously](http://stackoverflow.com/q/32193946/1048572). – Bergi Aug 25 '15 at 19:30

2 Answers2

0

Try changing

obj[property] = getExpandedObj(uuid, recursiveLevel-1)
   .then(function(exObj) {
     return exObj;
   });

to

return getExpandedObj(uuid, recursiveLevel-1)
 .then(function(exObj) {
    obj[property] = exObj;
    return obj;
});

because you were setting the value to be the promise object instead of the actual value.

Miguel Mota
  • 20,135
  • 5
  • 45
  • 64
0

The problem is that a) your mapping function does return nothing so it is not awaited b) you shouldn't use map here at all.

The perfect solution for this is Bluebird's Promise.props which awaits the promises on an object's properties.

function getUuid(value) {
     if (typeof value != "string") return null;
     var uuid = value.match(/\w{8}(-\w{4}){3}-\w{12}?/);
     if (uuid) return uuid[0];
     return null;
}
function getExpandedObj(uuid, recursiveLevel) {
    return getObj(uuid).then(function(obj) {
        // prevent infinite recursion
        if (recursiveLevel <= 0)
            return obj;
        for (var property in obj) {
            var uuid = getUuid(obj[property])
            if (uuid) {
                obj[property] = getExpandedObj(uuid, recursiveLevel-1);
            }
        }
        return Promise.props(obj);
    });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375