1

My friend and I are working with promises, and we are making sure that we are getting all pages of data before returning back to our initial call. Is there a more trivial way to approach this?

function getDocuments(startIndex, result, entries) {

    startIndex = typeof startIndex !== 'undefined' ? startIndex : 0;
    result = typeof result !== 'undefined' ? result : {};
    entries = typeof entries !== 'undefined' ? entries : [];

    // build our entries set with the result parameter

    for(var i in result.items) {
        try
        {
            var id = result.items[i].id;
            var name = result.items[i].name;
            var content = result.items[i].content;
            var entry = { "id": id, "name": name, "content": content };
            entries.push(entry);
        }
        catch(e) {
        }
    }

    // return a promise that fulfills a promise that then returns either a promise or a result.
    return new Promise(function(fulfill, reject) {
        // fulfill the promise and resolve the value, we pass a recursive promise as the value.
        fulfill(documentClient.getDocuments({ "startIndex": startIndex }).then(function(result) { // once our request is made, let's check the page count.
            var startIndex = result.startIndex;
            var pageSize   = result.pageSize;
            var totalCount = result.totalCount;
            if (startIndex + pageSize <= totalCount) { // if our current position is not at the end of the pages, return a promise with our current data and our current entries.
                return getDocuments(startIndex + pageSize, result, entries);
            }
            return entries; // otherwise our entries will bubble back up the stack and be resolved into the initial fulfill value.
        }));
    });
}

getDocuments().then(function(d) { console.log(d.length); });

My adjustments:

function getDocuments(startIndex, result, entries) {

    startIndex = typeof startIndex !== 'undefined' ? startIndex : 0;
    result = typeof result !== 'undefined' ? result : {};
    entries = typeof entries !== 'undefined' ? entries : [];

    // build our entries set with the result parameter

    // ...

    // return a promise that fulfills a promise that then returns either a promise or a result.
    return documentClient.getDocuments({ "startIndex": startIndex }).then(function(result) { // once our request is made, let's check the page count.
        var startIndex = result.startIndex;
        var pageSize   = result.pageSize;
        var totalCount = result.totalCount;
        if (startIndex + pageSize <= totalCount) { // if our current position is not at the end of the pages, return a promise with our current data and our current entries.
            return getDocuments(startIndex + pageSize, result, entries);
        }
        return entries; // otherwise our entries will bubble back up the stack and be resolved into the initial fulfill value.
    });
}

getDocuments().then(function(d) { console.log(d.length); });
Scott G.
  • 323
  • 1
  • 10
  • 1
    Please create a minimal working example. Your example contains a lot of unnecessary code. – Linus Oleander Feb 08 '16 at 21:00
  • 1
    You've demonstrated the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572) in its cleanest form (`Promise.resolve`) :-) – Bergi Feb 08 '16 at 22:06
  • So basically the antipattern is that I have initially returned a promise resolving a promise, when I could just return the first promise? – Scott G. Feb 08 '16 at 22:14

2 Answers2

1

Yes, you can chain the promises like this as documentClient.getDocuments returns a promise.

function getDocuments(startIndex, result, entries) {
    // ...
    return documentClient.getDocuments({ "startIndex": startIndex }).then(function(result) {
        // ...
        return entries; // otherwise our entries will bubble back up the stack and be resolved into the initial fulfill value.
    });
}

getDocuments().then(function(d) { console.log(d.length); });
Linus Oleander
  • 17,746
  • 15
  • 69
  • 102
0

Have a code path in getDocuments which does not end in a new promise

Here is a simple example

function defer(fn) {
    setTimeout(fn, 100);
}
function promiseChain(i, msg) {
    if (i <= 0) return msg; // end code path
    return new Promise((res, rej) => {
        defer(e => res(promiseChain(i - 1, msg)));
    });
}
promiseChain(10, "Hello World!").then(data => console.log(data));
// "Hello World!" logged after ten 100ms timeouts
Paul S.
  • 64,864
  • 9
  • 122
  • 138