0

I'm trying to write a function that includes a for loop inside a Promise, however the loop only performs on iteration and the promise is never resolved.

My code looks like this:

function appendPosts() {
    return functionThatReturnsAPromise()
       .then( result => {
           return new Promise( (resolve, reject) => {
              var list = [];
              result.forEach( item => {
                 //do stuff to item
                 list.push(item);
              });
             resolve(list);
           });
       })
       .then( list => {
          return new Promise( (resolve, reject) => {
             //This loop only runs once, even when list has contains many items
          for ( var i = 0; i < list.length; i++ ) {
             document.querySelector("someSelector").appendChild( list[i] );
          }
          resolve();
       });
   });
}

Clearly I'm doing something wrong. Any ideas?

Thanks for your time. - Daniel

Daniel Bernhard
  • 382
  • 3
  • 11
  • What is purpose of `Promise` constructor within `.then()`? Why do you iterate `result` only to push `item` to an array? – guest271314 Jun 03 '17 at 23:51
  • 1
    I don't think it's possible that the for loop runs only one time when list has longer length. Doublecheck the iterations and list.length. – xDreamCoding Jun 03 '17 at 23:55
  • 2
    Maybe an exception occurs in the first iteration? Use [`catch`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch). – maazadeeb Jun 03 '17 at 23:55
  • by the way - your code (as shown) is equivalent to https://jsfiddle.net/ms4yr8sr/ – Jaromanda X Jun 04 '17 at 00:39
  • 2
    As hinted, the return value of a promise reaction handler is used to resolve the promise returned from the `then` or `catch` call which added the handler. Returning a new promise synchronously resolved with a value instead of simply returning the value is redundant, and a bad example to follow if you read it somewhere. – traktor Jun 04 '17 at 01:36
  • @MaazSyedAdeeb is right. There was an exception thrown in the loop and I didn't have a catch block in place. guest271314 and Jaromanda X are also right that the syntax I was using was overly complicated. However simplifying the syntax didn't fix it -- catching the exception did. Thanks to everybody for their time and support. – Daniel Bernhard Jun 04 '17 at 15:38

2 Answers2

0

@MaazSyedAdeeb is right. There was an exception thrown in the loop and I didn't have a catch block in place. Thanks.

Daniel Bernhard
  • 382
  • 3
  • 11
0

The selector probably did not return a match, and so appendChild was called on undefined, triggering an exception translated to a rejected promise.

You could treat this error if in your call you add a .catch:

appendPosts().then(function () {
    console.log('all done');
}).catch(function (err) {
    console.log('error occurred: ', err);
});

But it should also be mentioned that you are using the promise constructor anti-pattern. Namely, in a then callback you can just return a value, and that value will become the promised value of the promise that then will return. So there is no need to do new Promise(). Instead, do this:

function appendPosts() {
    return functionThatReturnsAPromise().then( result => {
        // Just return the mapped array:
        return result.map( item => {
            //do stuff to item
            return item;
        }).then( list => {
            for ( var i = 0; i < list.length; i++ ) {
                // Make sure the selector will result in a match:
                document.querySelector("someSelector").appendChild( list[i] );
            }
        });
    });
}
trincot
  • 317,000
  • 35
  • 244
  • 286