NoobSter
NoobSter

Reputation: 1160

Cannot get nested promises to return value to next promise chain

Below, you'll see where i'm having an issue in the commented code. I have a nested promise which creates an object in a collection, then returns it.

But, I think i'm having an issue with async. The function completes before the created object is returned by the nested promise.

I'm still grasping promise chaining, and i'm probably doing a lot wrong here. Much of this may be cleared up if I could clean / flatten some of this.

 PostSchema.statics.createPost = function (o, user) {
    var whiskey;
    return Whiskey
        .createWhiskey(o.whiskey.value)
        .then(function (whiskeyData) {
            whiskey = whiskeyData.whiskey;
            o.post.whiskey = whiskeyData.whiskey._id;

            if (whiskeyData.whiskey.distiller) {
                o.post.distiller = whiskeyData.whiskey.distiller;
            }

            return o.distiller.new === true && !whiskey.distiller ? Distiller.newDistiller(o.distiller.value) : Promise.resolve()
                .then(function (distiller) {
                    //this never invokes   <---- it's called from the function below
                    console.log('never invokes', distiller).
                    if (distiller) {
                        whiskey.distiller = distiller._id;
                        //test this save
                        whiskey.save();
                        o.post.distiller = distiller._id;
                    }

                    var post = o.post;
                    post.user = user._id;
                    return Post
                        .createAsync(post)
                        .then(function (data) {
                            return Post
                                .populate(data, {
                                    path: 'user whiskey',
                                    populate: {
                                        path: 'distiller style',
                                    }
                                })
                        })

                        .then(function (populatedData) {
                            return (user.shareFB ? social.checkFB(user, populatedData) : Promise.resolve())
                                .then(function (FBres) {
                                    return (user.shareTWT ? social.checkTWT(user, populatedData) : Promise.resolve())
                                        .then(function (TWTres) {
                                            var socialData = [TWTres, FBres];
                                            return {
                                                'post': populatedData,
                                                'social': socialData
                                            };
                                        })
                                })
                        })
                })
        })
        .catch(function (err) {
            console.log('post create err : ', err);
        })
};

this is where the distiller is created and attempting to return:

DistillerSchema.statics.newDistiller = function (o) {

    return Distiller
        .findAsync({
            'name': o.name
        })
        .then(function (distiller) {
            if (distiller.length) {
                return distiller[0];
            }
            return Distiller
            .createAsync(o)
            .then(function (data) {
                //console.log here indicates that is is created <-- created and returned here
                console.log('distiller created ', data)
                return data;
            })
        })
        .catch(function(err) {
            console.log('create distiller err ', err);
        })
};

Upvotes: 0

Views: 323

Answers (1)

Bergi
Bergi

Reputation: 664307

Sounds like a grouping mistake. Instead of

return o.distiller.new === true && !whiskey.distiller
  ? Distiller.newDistiller(o.distiller.value)
  : Promise.resolve().then(…) // callback only called when no new distiller

you want

return (o.distiller.new && !whiskey.distiller
  ? Distiller.newDistiller(o.distiller.value)
  : Promise.resolve()
).then(…) // callback always called

At least that is how did all the other conditionals :-)

I'm still grasping promise chaining

After having learned that you always need to return from your asynchronous functions (which you did fine), you should have a look at how it is possible to flatten a chain (which applies to your code when all the conditionals are local expressions only, not early returns). Also I'd recommend not to indent chained method invocations as that quickly gets out of hand when nesting then callbacks, but that's just my personal preference.

Upvotes: 1

Related Questions