0

I am aware that a loop in js will not wait for the async process and therefor, will always be at the last iteration when the async process is done.

My Question is, how to I solve this so I can make the for loop wait for each iteration of the loop?

getChildItems() {
return new Promise((resolve, reject) => {

  this.lessons.levels.map((item, i) => {

      item.childlevels.map((childItem, iChild) => {

        ((i, iChild) => {
        this.horseman
        .open(childItem.url)
        .html()
        .then((html) => {
          cheerio(html).find('.list-item a').map((index, elem) => {
            let lesson = cheerio(elem);
            childItem.lessons.push(
              {name: lesson.text(), url: lesson.attr('href')}
            );
          });
        })
        .then(() => {
          const outter = i >= this.lessons.levels.length - 1;
          const inner = iChild >= item.childlevels.length - 1;

          if (outter && inner) {
            resolve(this.lessons);
          }
        });
      })(i, iChild);
      });
  });

});
}
Atomicts
  • 2,146
  • 2
  • 16
  • 13
  • Can you simplify the code? It is a little bit hard to understand what you want to implement with the code. – shaochuancs Aug 28 '17 at 09:37
  • waiting for asynchronous results in a loop is never simple ... which one of the two .map's did you want to do this in? – Jaromanda X Aug 28 '17 at 09:38
  • 1
    Possible duplicate of [Resolve promises one after another (i.e. in sequence)?](https://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence) – alexmac Aug 28 '17 at 09:38

2 Answers2

1

This is a bad practice to put asynchronous call inside a loop. You have two way to handle the problem.


1 - You want the functions to be called in parallel

Use of Promise.all. as example:

const rets = await Promise.all(this.lessons.levels.map(...));

2 - You want the functions to be called one after one other

Example inside this stackoverflow post.

Orelsanpls
  • 22,456
  • 6
  • 42
  • 69
  • Getting an issue with using await, i added async to the arrow function it is situated in and I am getting the error: `SyntaxError: missing ) after argument list` and `return new Promise(async function (resolve, reject) {` – Atomicts Aug 28 '17 at 14:12
  • You can either use async/await (ES8), either use promise (ES6). `async function() {` or `function() { return new Promise(` – Orelsanpls Aug 28 '17 at 14:36
  • Promise.all using async/await `await Promise.all(...)`; Using promise `Promise.all(...).then(...).catch(...)` – Orelsanpls Aug 28 '17 at 14:37
  • Thanks, but now I seem to be getting the error ' `Unhandled rejection HeadlessError: Phantom Process died` which i am guessing is because the headless browser is getting closed before the requests have been made which means I am doing something wrong. I'm fairly new to Node.js please can you give an example of what to do within the Promise.all() as it seems like it is not currently waiting for the request to be made. (I am using the ES6 version) – Atomicts Aug 28 '17 at 22:11
0

You can use Bluebird's Promise.each. This waits for your promises to return before running the next iteration

Promise.each([item1,item2,item3,item4], function(item, index) => {
  // data manipulation with item if needed
  return Promise.resolve(async_action(with_item))
})
Prasanna
  • 4,125
  • 18
  • 41