ECMAScript 2017 并发异步函数是否有可能等待不应并发的子承诺?

ECMAScript 2017 concurrent async functions with possibility to wait for subpromises that should not be concurrent?

假设我们有多个并发任务,每个任务至少在某一时刻执行一个 Web 请求,并且它们需要一段时间才能完成。假设他们也可能会或可能不会在某个任意点执行 运行 一个 return 承诺的函数。假设还需要确保其中一些承诺永远不会同时 运行。

我可以在所有这些并发任务相遇的地方创建一个集合点,从那些 return 承诺不应同时 运行 的函数中创建一个承诺链,然后继续这一切都完成后。如果这些任务中的一些任务比其他任务明显更快地到达集合点但在集合点之后仍有很多工作要做,那么这有一个潜在的无用等待的缺点。

另外,我试过像这样实现一个简单的承诺队列:

function PromiseQueue() {
    var promise = Promise.resolve();

    return {
        push: function(fn) {
            promise = promise.then(fn, fn);
            return this;
        }
    }
}

这个队列可以工作,但有一个问题,我看不到一种方法可以将函数从一个并发任务发送到队列,并且还等待只有在队列决定处理后才可用的结果已发送项,更不用说在将函数发送到队列时尚未构建承诺,因此在将承诺生成函数发送到队列时没有什么可等待的。

我想通过尽可能坚持 ECMAScript 2017 async/await 格式和 ES6 承诺来实现上述目标。

下面是 2 个并发任务所描述问题的示例,其中 subPromise1 和 subPromise2 不应同时执行,但目前编写的有可能,但我想要一个任意数量的通用解决方案并发任务数。

async function async1() {
    //do some long running work
    const sPResult = await subPromise1;
    //do some more long running work depending on sPResult
}

async function async2() {
    //do some different long running work
    const sPResult = await subPromise2;
    //do some more different long running work depending on sPResult
}

async function mainFunction() {
    //something
    const totalResult = await Promise.all([async1,async2]);
    //something else
}

编辑: 这是一个有效的 fiddle,其中可以看到最初描述的问题:https://jsfiddle.net/40gchrw6/

编辑: 这是一个可行的解决方案:https://jsfiddle.net/f2ewsugm/1/

为必须按顺序执行的承诺链创建封闭范围(class 可能有意义)。当您到达必须按顺序执行的步骤时,将其添加到链中。

Class AsyncThing {
  constructor() {
    this.promises = Promise.resolve()
  }

  async async1() {
    //do some long running work
    // assuming subPromise1 is a promise-returning function that must be chained
    let sPResult
    this.promises = this.promises.then(subPromise1).then(result => sPResult = result)
    await this.promises;
    //do some more long running work depending on sPResult
  }

  async async2() {
    //do some different long running work
    // assuming subPromise2 is a promise-returning function that must be chained
    let sPResult
    this.promises = this.promises.then(subPromise2).then(result => sPResult = result)
    await this.promises;
    //do some more different long running work depending on sPResult
  }

  async mainFunction() {
    //something
    const totalResult = await Promise.all([async1,async2]);
    //something else
  }
}