Как правильно написать облачные функции, которые автоматически обновляют документы firestore

#node.js #firebase #google-cloud-firestore

#node.js #firebase #google-cloud-firestore

Вопрос:

Я пытаюсь написать облачную функцию firebase, которая запускает простой цикл while каждый раз, когда новый пользователь создает учетную запись. По какой-то причине функция обновления запускается только один раз и останавливается. Код, который я использую, вставлен ниже

 const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp();

const firestore = admin.firestore();
var data;
var counter = 0;


 exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
   data = snapshot.data();
   while (counter < 5) {
    setInterval(updateCounter(counter), 5000);
  }
  
 })

 async function updateCounter(counter){
  await firestore.collection('testCollection').doc(data['username']).update({
    counter: admin.firestore.FieldValue.increment(1)
  });
  counter  ;
 }


 

Комментарии:

1. Почему вы используете setInterval внутри своего цикла?

2. я хочу, чтобы функция «updateCounter» запускалась через установленное время в течение 5 раз

Ответ №1:

Cloud Functions прекращает выполнение вашего кода, когда он достигает финала } вашей функции, так как в противном случае он будет выставлять вам счет на неопределенный срок.

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

 exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
  data = snapshot.data();
  return Promise((resolve, reject) => {
    while (counter < 5) {
      setInterval(updateCounter(counter), 5000);
    }
    setInterval(() => {
      if (counter >= 5) {
        resolve()
      }
    }, 5000)
  })
})
 

Обратите внимание, что while (counter < 5) цикл в коде по-прежнему не будет выполнять то, что вы ожидаете, но, по крайней мере, теперь функция продолжит выполняться в течение нескольких мгновений, и счетчик будет увеличен.


Вероятно, это то, что вы хотите:

 exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
  data = snapshot.data();
  return Promise((resolve, reject) => {
    setTimeout(updateCounter,  5000);
    setTimeout(updateCounter, 10000);
    setTimeout(updateCounter, 15000);
    setTimeout(updateCounter, 20000);
    setTimeout(updateCounter, 25000);
    setInterval(() => {
      if (counter >= 5) {
        resolve()
      }
    }, 5000)
  })
})
 

Этот вызов updateCounter выполняется 5 раз, каждые 5 секунд после предыдущего вызова. Существует вероятность того, что окончательное обновление базы данных не будет завершено до вызова resolve , поэтому я настоятельно рекомендую узнать больше об асинхронном поведении, прочитав документацию по синхронизации, асинхронности и обещаниям и просмотрев серию «Отличные обещания и асинхронное поведение в облачных функциях» Дуга.

Ответ №2:

если требуется запускать эту функцию 5 раз, раз в 5 секунд, это может сработать.

 for (let i =0;i<5;i  ){
  await updateCounter();
  await sleep (5000);
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}