Как зациклить код асинхронного запроса firebase? - PullRequest
0 голосов
/ 03 апреля 2019

Я пытаюсь зациклить и получить разные документы из пожарного магазина. «Идентификаторы документов» предоставляются массивом «cart», как показано в приведенном ниже коде.

Логика программирования, которую я попробовал, выглядит следующим образом: цикл while на каждой итерации получает документ из firestore и в первом разделе «then» сохраняет только что полученные данные, а во втором «then» увеличивает «i». и выполняет следующий цикл цикла.

Проблема в том, что цикл не ожидает завершения запроса get. Это просто продолжает цикл и вылетает.

Дело в том, что даже если мне как-то удастся сделать правильную часть цикла. Как бы я управлял всем потоком выполнения программы, чтобы только после завершения части цикла выполнялся дополнительный код, поскольку приведенный ниже код использует массив cart, который обновляет часть цикла.

let i = 0
while (i < cart.length) {
    let element = cart[i]
    db.collection(`products`).doc(element.productID).get().then((doc1) => {
        element.mrp = doc1.data().mrp
        element.ourPrice = doc1.data().ourPrice
        return console.log('added price details')
    }).then(() => {
        i++;
        return console.log(i)
    }).catch((error) => {
        // Re-throwing the error as an HttpsError so that the client gets the error details.
        throw new functions.https.HttpsError('unknown', error.message, error);
    });
}
return db.collection(`Users`).doc(`${uid}`).update({
    orderHistory: admin.firestore.FieldValue.arrayUnion({
        cart,
        status: 'Placed',
        orderPlacedTimestamp: timestamp,
        outForDeliveryTimestamp: '',
        deliveredTimestamp: ''
    })
}).then(() => {
    console.log("Order Placed Successfully");
})

Ответы [ 2 ]

1 голос
/ 03 апреля 2019

Ваш вопрос не о firebase, вы спрашиваете об асинхронном цикле.Вы можете увидеть promises примеры здесь и async/await здесь

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

cart.reduce(
  (promise, element) =>
    promise.then(() => {
      return db.collection(`products`)
        .doc(element.productID)
        .get()
        .then(doc1 => {
          element.mrp = doc1.data().mrp;
          element.ourPrice = doc1.data().ourPrice;
        });
    }),
  Promise.resolve()
);

Если вы можете, вместо этого используйте async/await.Здесь все обещания создаются одно за другим.

async function fetchCart() {
  for (const element of cart) {
    const doc1 = await db.collection(`products`).doc(element.productID);
    element.mrp = doc1.data().mrp;
    element.ourPrice = doc1.data().ourPrice;
    console.log('added price details');
  }
}
0 голосов
/ 03 апреля 2019

Каждый вызов Cloud Firestore происходит асинхронно. Таким образом, ваш while цикл запускает несколько таких запросов, но не ожидает их завершения.

Если у вас есть код, который требует всех результатов, вам нужно будет использовать Promises, чтобы обеспечить поток. Вы уже используете обещание в цикле while, чтобы получить doc1.data().mrp. Если cart является массивом, вы можете сделать следующее, чтобы собрать все обещания о загрузке данных:

var promises = cart.map(function(element) {
   return db.collection(`products`).doc(element.productID).get().then((doc1) => {
        return doc1.data();
    });
});

Теперь вы можете ждать всех данных с помощью:

Promise.all(promises).then(function(datas) {
  datas.forEach(function(data) {
    console.log(data.mrp, data.ourPrice);
  });
});

Если вы находитесь в современной среде, вы можете использовать async / await, чтобы абстрагироваться от then:

datas = away Promise.all(promises);
datas.forEach(function(data) {
  console.log(data.mrp, data.ourPrice);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...