Триггеры базы данных Firebase в реальном времени: когда асинхронно, а когда нет - PullRequest
0 голосов
/ 21 ноября 2018

В документации по триггерам Firebase мы не видим слово async: https://firebase.google.com/docs/functions/database-events#reading_the_previous_value Допустим, у меня есть две версии функции, одна с async, а другая без, например:

exports.recountTotalCaloriesOnUpdate2 = functions.database.ref('/mealsOf/{userId}/{day}/meals')
    .onUpdate(
        (change,context) => {
            let uid= context.params.userId;
            let day= context.params.day;
            if ( !change.after.exists() ) return null ;
            if ( !change.before.exists() ) return null ;
            const collectionRef = change.after.ref;
            let finalSum = collectionRef.ref.once('value').then((snap) => {
                let sum = 0;
                snap.forEach((child) => {
                    //console.log(child.val().numCalories);
                    sum = sum + parseInt(child.val().numCalories);
                });
                return sum;
            });
            /*
            return await counterRef.ref.transaction((cnt) => {
                 return finalSum;
            });
            */
            return dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum);
            /*
            return await dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum).then( (a) => {
                return null ;
            }).catch( (error) => {
                return null ;
            });
            */
        }
    );

и с async:

exports.recountTotalCaloriesOnUpdate2 = functions.database.ref('/mealsOf/{userId}/{day}/meals')
    .onUpdate(
        async(change,context) => {
            let uid= context.params.userId;
            let day= context.params.day;
            if ( !change.after.exists() ) return null ;
            if ( !change.before.exists() ) return null ;
            const collectionRef = change.after.ref;
            let finalSum = await collectionRef.ref.once('value').then((snap) => {
                let sum = 0;
                snap.forEach((child) => {
                    //console.log(child.val().numCalories);
                    sum = sum + parseInt(child.val().numCalories);
                });
                return sum;
            });
            /*
            return await counterRef.ref.transaction((cnt) => {
                 return finalSum;
            });
            */
            //return dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum);
            return await dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum).then( (a) => {
                return null ;
            }).catch( (error) => {
                return null ;
            });
        }
    );

В чем разница?Это имеет значение для Firebase?Кроме того, при вычислении finalSum, мой let finalSum = await ..., я проверяю, доступен ли этот finalSum в последующих строках, т. Е. Выполняет ли поток выполнения .join() вычисление на языке Java?Но настоящая проблема с этим кодом состоит в том, что

return await dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum).then( (a) => {
                return null ;
            }).catch( (error) => {
                return null ;
            });

всегда дает мне сообщение: enter image description here для случая без async и enter image description here для дела с async.

У меня есть путь mealsOf/{userId}/{day}/meals/{mealId}, и я проталкиваю туда новую еду.Поэтому я установил этот триггер для обновления счетчика на mealsOf/{userId}/{day}/totalCalories всякий раз, когда происходит запись / обновление по пути mealsOf/{userId}/{day}/meals.Как справиться с вышеуказанными исключениями?

РЕДАКТИРОВАТЬ: Вы можете прочитать о async/await в другом месте, например, https://hackernoon.com/understanding-async-await-in-javascript-1d81bb079b2c (просто случайная ссылка, потеря материала там!) Что касается моего конкретного случаяЯ позволил async быть там, обратил внимание на фактическое сообщение об ошибке и заменил последнюю строку на это:

return dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(""+finalSum, (error) => {
                if ( error )
                    console.log(error.message);
            });

и, наконец, получил мои тесты с чистым выполнением.Итак, NaN говорит нам, что безопаснее всего конвертировать все в строку.

РЕДАКТИРОВАТЬ: Посмотрите Функции Firebase: Непонятная «ошибка соединения» , чтобы увидеть, что даже в последней вставленной мной строке должно быть ключевое слово await.В противном случае иногда вы можете получить ошибку connection error из-за неразрешенных обещаний.

1 Ответ

0 голосов
/ 02 января 2019

У меня очень похожая проблема, с которой я не могу обойти анализатор функций.

exports.triggerInvoiceCreate = functions.firestore
  .document('accounts/{businessId}/projects/{projectId}')
  .onUpdate(async (change, context) => {
    try {
      const businessId = context.params.businessId
      const project = change.after.data()

      const clientRef = await admin
        .firestore()
        .doc(`accounts/${businessId}/clients/${project.client.id}`)
        .get()
      const client = clientRef.data()
      return Promise.resolve(client)
    } catch (error) {
      console.log(error)
      return Promise.reject(error)
    }
  })

Понятия не имею, почему я получаю:

Detailed stack trace: /user_code/index.js:23
  .onUpdate(async (change, context) => {
              ^
SyntaxError: Unexpected token (
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...