Как ждать обещание внутри al oop и функцию обещания - PullRequest
0 голосов
/ 29 января 2020

Я пытаюсь дождаться многообещания внутри al oop. Этот l oop должен повернуться 3 раза, посылая массив из 3 предметов. Два начальных цикла будут отправлять 1000 товаров каждый, а третий отправляет 500.

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

enter image description here

Мой метод

const MAXIMUM_POST_SIZE = 1000
export const addProducts = (products) => new Promise(
  (resolve, reject) => {
    for (let i = 0; i < Math.ceil(products.length / MAXIMUM_POST_SIZE); i += 1) {
      const indexToStartExtraction = i * MAXIMUM_POST_SIZE;
      const sizeOfExtraction = indexToStartExtraction + MAXIMUM_POST_SIZE;
      const extractedProducts = products.slice(indexToStartExtraction, sizeOfExtraction);
      const ref = firebase.ref('products');
      const normalizedPostData = arrayToJsonObjectWithUid({ products: extractedProducts, ref });

      console.log(extractedProducts.length);

      ref.update(normalizedPostData).then(() => {
        console.log(`Doing ${i} call`);
        resolve(true);
      })
        .catch((err) => reject(err));
    }
  },
);

Я пытался сделать это без успеха:

export const addProducts = (products) => new Promise(
  (resolve, reject) => {
    const promises = [];

    for (let i = 0; i < Math.ceil(products.length / MAXIMUM_POST_SIZE); i += 1) {
      const indexToStartExtraction = i * MAXIMUM_POST_SIZE;
      const sizeOfExtraction = indexToStartExtraction + MAXIMUM_POST_SIZE;
      const extractedProducts = products.slice(indexToStartExtraction, sizeOfExtraction);
      const ref = firebase.ref('products');
      const normalizedPostData = arrayToJsonObjectWithUid({ products: extractedProducts, ref });

      console.log(extractedProducts.length);

      promises.push(ref.update(normalizedPostData));
    }
    Promise.all(promises)
      .then(() => resolve())
      .catch(() => reject());
  },
);

Как правильно ждать каждое обещание?

Ответы [ 2 ]

1 голос
/ 29 января 2020

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

Это фрагмент кода простое для l oop выполнение асинхронных действий:

function someAsyncFn (i) {
  return new Promise ((resolve) => setTimeout(() => {
    console.log(i)
  }, 100))
}

const promises = []
for (let i=0; i<5; i++) {
  promises.push(someAsyncFn(i))
}

Promise.all(promises)

Обратите внимание, как это возвращает правильные значения после выполнения

Теперь нам нужно то же самое, но применить к вашей базе кода:

function addProducts (products) {
  return new Promise(
    (resolve, reject) => {
      const promises = [];
      const ref = firebase.ref('products');
      const max = Math.ceil(products.length / MAXIMUM_POST_SIZE)

      for (let i = 0; i < max; i++) {
        const indexToStartExtraction = i * MAXIMUM_POST_SIZE;
        const sizeOfExtraction = indexToStartExtraction + MAXIMUM_POST_SIZE;
        const extractedProducts = products.slice(indexToStartExtraction, sizeOfExtraction);
        const normalizedPostData = arrayToJsonObjectWithUid({ products: extractedProducts, ref });
        promises.push(ref.update(normalizedPostData));
      }

      Promise.all(promises)
        .then(resolve)
        .catch(reject);
    },
  );
}

Я сделал некоторую очистку, но идея та же самая, можете ли вы попробовать этот код и посмотреть, дает ли он правильный результат?

0 голосов
/ 29 января 2020

Насколько я понимаю, вы хотите запускать их последовательно. Ваш текущий код с Promise.all будет запускать их параллельно.

Если вы хотите запустить их последовательно, проще всего (поскольку вы используете Node.js) - использовать функцию async и await:

const MAXIMUM_POST_SIZE = 1000
export const addProducts = async (products) => {
  for (let i = 0; i < Math.ceil(products.length / MAXIMUM_POST_SIZE); i += 1) {
    const indexToStartExtraction = i * MAXIMUM_POST_SIZE;
    const sizeOfExtraction = indexToStartExtraction + MAXIMUM_POST_SIZE;
    const extractedProducts = products.slice(indexToStartExtraction, sizeOfExtraction);
    const ref = firebase.ref('products');
    const normalizedPostData = arrayToJsonObjectWithUid({ products: extractedProducts, ref });

    console.log(extractedProducts.length);

    console.log(`Doing ${i} call`);
    await ref.update(normalizedPostData);
  }
  return true;
};

. Любая неопределенно последняя версия Node.js поддерживает функции async.

Эта функция возвращает обещание, которое будет:

  • Отклонить, если отклонен любой из вызовов ref.update, или
  • Выполнить со значением true, когда все они успешно завершили

Он ждет, пока каждый из них завершит sh, прежде чем начать следующий. Напротив, ваша версия с Promise.all запускает все обновления, позволяет этим обновлениям запускаться одновременно, а затем ждет, пока они все не завершатся.

Обратите внимание, что все, что вызывает addProducts, должно будет ждать своего обещания для расчета, если все, что приходит после того, как addProducts вызов может выполняться одновременно с вызовами обновления, addProducts запускается.

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