Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

return value inside promise chain isn't getting called

I'm using the promise library Bluebird and I'm currently running into the issue that everything inside the function runs great, but when I try to return a value, the function instead returns undefined.

This is the promise chain:

function foo() {
    createGroupMembers(parsedChat).then(function(val) {
        var members = val;

        createMessages(parsedChat, maxPages).then(function(val) {
            var messages = val;

            Promise.all([ createFrontCover(subject, firstdateOfMessages, lastDateOfMessages, isPreview), createStats(parsedChat), createBackCover(parsedChat)])
            .then(function (results) {
                var front = results[0];
                var stats = results[1];
                var backcover = results[2];

                var book = head + front + stats + members + messages + backcover;

                console.log('pages in this book: ', pages);
                console.log(book); // logs perfect values.

                return book; 
            }); 

       });

    });
}

The problem is simple: when calling foo(), it's value becomes undefined instead of book. Why am I experiencing this behaviour?

like image 271
bdv Avatar asked Oct 07 '15 00:10

bdv


People also ask

How do you return a value inside a promise?

Promise resolve() method: If the value is a promise then promise is returned. If the value has a “then” attached to the promise, then the returned promise will follow that “then” to till the final state. The promise fulfilled with its value will be returned.

How do you call a promise inside a promise?

Here we need to first declare a Promise by using the Promise syntax, and we will be using the then() method for its execution and then inside that then() method we will create another promise by using the same Promise syntax as illustrated above, and then we will call our result of first inside that new Promise.

How do you handle nested promises?

In a promise nesting when you return a promise inside a then method, and if the returned promise is already resolved/rejected, it will immediately call the subsequent then/catch method, if not it will wait. If promised is not return, it will execute parallelly.


1 Answers

function foo() {
    return createGroupMembers(parsedChat).then(function(val) {
        var members = val;

        return createMessages(parsedChat, maxPages).then(function(val) {
            var messages = val;

            return Promise.all([createFrontCover(subject, firstdateOfMessages, lastDateOfMessages, isPreview), createStats(parsedChat), createBackCover(parsedChat)])
                .then(function(results) {
                    var front = results[0];
                    var stats = results[1];
                    var backcover = results[2];

                    var book = head + front + stats + members + messages + backcover;

                    console.log('pages in this book: ', pages);
                    console.log(book); // logs perfect values.

                    return book;
                });

        });

    });
}

Now foo will return a promise which can resolve to the value of book

foo().then(function(book) {
    console.log('huzzah I have book ' + book);
});

To be honest, foo could be rewritten, but that's a different question altogether

FYI: you could do something like this for foo

function foo() {
    return createGroupMembers(parsedChat)
    .then(function(members) { // members
        return Promise.all([members, createMessages(parsedChat, maxPages)]);
    })
    .then(function(members_messages) {  // membersMessages
        return Promise.all([createFrontCover(subject, firstdateOfMessages, lastDateOfMessages, isPreview), createStats(parsedChat)].concat(members_messages, [createBackCover(parsedChat)]));
    })
    .then(function(results) { // front, stats, members, messages, back
        var book = head + results.join('');

        console.log('pages in this book: ', pages);
        console.log(book); // logs perfect values.

        return book;
    });
}

Messed around with the order in the second (was your only) Promise.all, and added the previous Promise results in it to make the final conatenation of parts as simple as a .join - doing it this way will also propagate any erros correctly, so your usage of foo can be

foo().then(function(book) {
    console.log('huzzah I have book ' + book);
}).catch(function(err) {
    // handle any and all errors here
});
like image 187
Jaromanda X Avatar answered Oct 18 '22 09:10

Jaromanda X