按顺序执行未确定数量的Promise

时间:2017-11-14 07:49:01

标签: javascript ecmascript-6 promise bluebird q

我有这个类,方法next返回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);
        });
    }
}

虽然示例显示100,但它可以返回无限数量的承诺。

我需要按顺序执行所有承诺。

我怎样才能实现它?

到目前为止,我提出的解决方案只是递归的:

const source = new PromiseGenerator();

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

据我所知Node does not optimize tail calls,这可能会导致筹码增长。

有更好的方法吗?

如果有一些Promise库有它可以工作但是理解如何在没有库的情况下实现它会很好。

更新1:抱歉,我没有立即说清楚:我无法控制PromiseGenerator课程,这是我可以使用但无法改变的。所以问题是如何处理这种情况。

更新2:我使用了@eikooc解决方案:没有generators,只有async/await。见下面的例子。

谢谢!

1 个答案:

答案 0 :(得分:2)

Generators与此完美匹配。使用function*关键字构建生成器:

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

然后用:

来调用它
const source = promiseGenerator()
source.next()

这将继续为您提供新值。返回看起来像{value: Promise, done: false},直到完成。 生成器完成后,done值将更改为true

如果你想继续使用这个类,只想要一个循环。您还可以将班级与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()