Параллельные асинхронные функции ECMAScript 2017 с возможностью ожидания подпрограмм, которые не должны быть параллельными?

Предположим, у нас есть несколько одновременных задач, каждая из которых выполняет хотя бы один веб-запрос в тот или иной момент, и для их выполнения требуется некоторое время. Предположим, что они также могут или не могут в какой-то произвольный момент выполнения запускать функцию, которая возвращает обещание. Предположим, также необходимо убедиться, что некоторые из этих промисов никогда не выполняются одновременно.

Я мог бы создать единую точку встречи, где встретились бы все эти параллельные задачи, создать цепочку промисов из тех функций, которые возвращают промисы, которые не должны выполняться одновременно, и продолжить после того, как все это будет сделано. У этого есть обратная сторона потенциального бесполезного ожидания, если некоторые из этих задач достигают точки встречи значительно раньше, чем другие, но все еще имеют много работы после точки встречи.

Кроме того, я попытался реализовать простую очередь обещаний, например:

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

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

Эта очередь работает, но есть проблема, заключающаяся в том, что я не вижу способа отправить функцию в очередь из одной из параллельных задач, а также дождаться результатов, которые будут доступны только после того, как очередь решит обработать отправленный элемент, а не упомяните, что обещание еще не создано в момент отправки функции в очередь, поэтому нечего ждать в момент отправки функции создания обещания в очередь.

Я хотел бы достичь вышеупомянутого, придерживаясь формата async/await ECMAScript 2017 и обещаний ES6, насколько это возможно.

Ниже приведен пример описанной проблемы с двумя одновременными задачами, где 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
}

EDIT: Вот работающая скрипта, в которой можно увидеть проблему, описанную изначально: https://jsfiddle.net/40gchrw6/

EDIT: Вот рабочее решение: https://jsfiddle.net/f2ewsugm/ 1/


person shaomonksn    schedule 05.01.2020    source источник


Ответы (1)


Создайте объемлющую область (класс может иметь смысл) для цепочки обещаний, которые должны выполняться последовательно. Когда вы дойдете до шага, который должен быть последовательным, добавьте его в цепочку.

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
  }
}
person danh    schedule 05.01.2020
comment
Отлично, как раз то, что я искал. И я предполагаю, что это не должно вызывать накопление стека в случае, если mainFunction вызывается несколько раз? Или безопаснее просто сбросить обещания в Promise.resolved() в конце выполнения mainFunction? Также я подготовил скрипт с рабочим решением, так как это может помочь кому-то в будущем: jsfiddle.net/f2ewsugm/ 1 - person shaomonksn; 06.01.2020