14

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?

bdv
  • 1,154
  • 2
  • 19
  • 42
  • 2
    foo doesn't return anything at all – Jaromanda X Oct 07 '15 at 00:20
  • I'm not familiar with Bluebird, but I have used native JS promises. Having said that... the anonymous function `function(results)` returns book. The two anonymous functions `function(val)` above it return nothing. `foo`, in the end, does not return anything. – sg.cc Oct 07 '15 at 00:20
  • You need to return all your nested functions. createGroupMembers, createMessages, etc. – ehynds Oct 07 '15 at 00:21
  • @JaromandaX How can I make it return anything, and why doesn't it return? – bdv Oct 07 '15 at 00:21

1 Answers1

26
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
});
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87