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

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

const reqs = [...Array(10)].map(() => () => axios.post('http://localhost:7000/test', {}))


const handleChunks = (reqs) => {
    const chunks = []
    const chunkSize = 5
    for (let i = 0; i < reqs.length; i += chunkSize) {
      chunks.push(reqs.slice(i, i + chunkSize))
    }
    chunks.reduce(async (acc, chunk) => {
      const chunkToPromise = chunk.map((chunkFunc) => chunkFunc())
      return Promise.all(chunkToPromise).then(async (result) => {
          acc = await acc
          acc.push(result)
          return acc
      })
    }, Promise.resolve([]))
}

Мне кажется, что все обещания, которые я создаю, уже объявляются в очереди задач, и что Promise.all на самом деле берет не то, что вы ему дали, а все обещания, которые находятся в очереди задач.

Кто-нибудь знает, как решить эту проблему?

Изменить: я обнаружил, что на клиенте работает так же ...

1
Tslil Crispel 20 Янв 2021 в 15:45

2 ответа

Лучший ответ

Здесь есть три аспекта: разбиение на фрагменты, запуск фрагмента и ожидание их завершения. Создадим несколько помощников:

// NOTE: works but probably not optimal. I fired this off the top of my head,
// for something like this in production I'd use a library function from
// lodash or ramda or something.
const partition = (n, xs) => {
  const results = [];
  let i = k = 0;
  while (i < xs.length) {
    results.push([]);
    while (k < n) {
      if (i === xs.length) break;
      results[results.length - 1].push(xs[i]);
      i++;
      k++;
    }
    k = 0;
  }
  return results; 
};

// This will make the requests from the passed in array and
// wait for them all to finish. Note that unlike Promise.all
// allSettled will not bail early if you get a rejection.
const runPromiseFns = async (ps) => Promise.allSettled(ps.map(x => x()));

// This will take an array of arrays of Promise generating functions
// and wait for each sub-array to settle before moving on
// to the next one.
const runChunks = async (chunks) => {
  for (let chunk of chunks) {
    await runPromiseFns(chunk);
  }

  return;
};

Отлично. И сейчас:

// Array of request thunks from your original code
const reqs = [...Array(10)].map(() => () => axios.post('http://localhost:7000/test', {}));

// Break into chunks of 5
const chunks = partition(5, reqs);

// Run through the execution pipe. Here allDone is a
// Promise you can .then or await somewhere else.
const allDone = runChunks(chunks);
0
Jared Smith 20 Янв 2021 в 14:11
const promiseAllFn = (pollingRequests) => Promise.all(pollingRequests.map((pollingRequest) => callApi(pollingRequest)));

    chunk(Object.values(subRegister), 4).reduce(
        (prev, pollingRequests) => prev.then(() => promiseAllFn(pollingRequests)),
        Promise.resolve('start')
    );
0
Daniel Duong 20 Янв 2021 в 21:53