SmxCde
SmxCde

Reputation: 5403

Go through undetermined number of Promises sequentially

I have this class that has method next returning a Promise.

class PromiseGenerator {
    constructor() {
        this.limit = 100;
        this.counter = 0;
    }
    next() {
        this.counter++;
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(this.counter <= this.limit ? this.counter : false);
            }, 500);
        });
    }
}

Though example shows 100 it could return unlimited number of promises.

I need to execute all the promises in sequential order.

How can I achieve it?

Only solution I came up so far is recursive:

const source = new PromiseGenerator();

(function loop() {
    source.next().then(counter => {
        if (counter) {
            console.log(counter);
            loop();
        } else {
            console.log('Done');
        }
    });
})();

As I understand Node at the moment does not optimize tail calls and it may lead to stack growth.

Is there a better way of doing this?

if some Promise library has it it will work but it would be nice to understand how to achieve it without library as well.

Update 1: Sorry I didn't make it clear right away: I am not in control of PromiseGenerator class, it is something I can use but cannot change. So the question is how to handle this situation.

Update 2: I went with @eikooc solution: Without generators but just with async/await. See example below.

Thanks!

Upvotes: 0

Views: 76

Answers (1)

eikooc
eikooc

Reputation: 2563

Generators are a perfect match for this. Construct a generator with the function* keyword:

function* promiseGenerator() {
  while(!someCondition) {
    yield new Promise((resolve, reject) => {})
  }
}

And then call it with:

const source = promiseGenerator()
source.next()

This will continue to give you new values. The return looks like this {value: Promise, done: false} until it is finished. When the generator finishes the done value will change to true

If you want to keep using the class and just want a loop. You can also combine your class with a async function:

async function loop() {
  const source = new PromiseGenerator()
  while (true) {
    const result = await source.next()
    if (result) {
      console.log(result)
    } else {
      console.log('done')
      break
    }
  }
}

loop()

Upvotes: 3

Related Questions