Как запустить "х" обещания параллельно Javascript - PullRequest
0 голосов
/ 26 августа 2018

У меня есть функция "promiseFunction", которая возвращает обещание, которое разрешается позднее.

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

Функция вызывает некоторый внешний однопоточный c-код на моем компьютере, если я вызываю слишком много экземпляров этого кода за раз, то происходит сбой моей системы, но если я вызываю его последовательно по 1 за раз, это очень медленно, так как толькоодна нить моего процессора делает любую работу.

Итак, я пришел с кодом ниже, однако он не работает.Он будет вызывать первые 10 обещаний параллельно, но постепенно он начинает вызывать все меньше и меньше обещаний одновременно, пока не вызовет только 1 обещание за раз.

var totalNumberOfPromises = // total number times to run promiseFunction;
var promiseCounter = 0; // keep track of which promise call this is 
for(w=0;w<10;w++){ // run 10 promises at a time
  promiseFunction().then(function(resolve) {
    loadNewPromise();
  })
  promiseCounter++;
}

function loadNewPromise(){

  if(promiseCounter<totalNumberOfPromises){
    promiseFunction().then(function(resolve) {  loadNewPromise(); });
  }else{
    alert("Finished");
  }
  promiseCounter++;
}

Что-то не так с приведенным выше кодом, вызывающим такое поведение?И есть ли стандартный способ сделать это?

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

Как насчет этого?Если вы создаете свои queue, а это Array из functions, которые возвращают Promise, вы можете splice кусков из него и обработать каждый с Promise.all.

const fakePromise = (id) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(`Resolving promise ${id}`)
      resolve(id)
    }, 100)
  })
}

const queue = Array(100).fill().map((_, i) => {
  return () => fakePromise(i)
})

const batchProcessPromises = (promises, batchSize) => {
  if (promises && promises.length) {
    return Promise.all(
      promises.splice(0, batchSize)
        .map(promise => promise())
    )
      .then(() => {
        console.log('Batch complete')
        return batchProcessPromises(promises, batchSize)
      })
  }
  console.log('Batch complete')
  return Promise.resolve()
}

batchProcessPromises(queue, 10)
  .then(() => {
    console.log('Time to get one with my day')
  })

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

batchProcessPromises([...queue], 10)
  .then(() => {
    console.log('Time to get one with my day', queue)
  })

Fiddle здесь https://jsfiddle.net/stwilz/2bpdcxo6/24/

0 голосов
/ 26 августа 2018

Вот функция, которую я подготовил ранее (я использовал ее в течение нескольких лет только для такой вещи

const multiQueue = length => {
    length = (isNaN(length) || length < 1) ? 1 : length;
    const q = Array.from({length}, () => Promise.resolve());
    let index = 0;
    const add = cb => {
        index = (index + 1) % length;
        return (q[index] = q[index].then(() => cb()));
    };
    return add;
};

// demo usage

const q = multiQueue(10);

let inFlight = 0;
let maxInFlight = 0;
const promiseFunction = (i) => {
  	inFlight++;
    maxInFlight = Math.max(inFlight, maxInFlight);
    const obj = {inFlight, maxInFlight, i};
    return new Promise(resolve => {
        setTimeout(() => {
            inFlight--;
            resolve(Object.assign(obj, {t:performance.now()}));
        }, 10 );
    })
};

for (let i = 0; i < 40; i++) {
    q(() => promiseFunction(i)).then(v => console.log(JSON.stringify(v)));
}

Вы видите, что самое большее 10 запросов "inFlight"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...