Проблемы с чтением данных в Firebase Cloud Function - PullRequest
0 голосов
/ 19 января 2020

Попытка прочитать pushToken от данного пользователя в коллекции пользователей (после операции обновления в другой коллекции) возвращает неопределенное значение

exports.addDenuncia = functions.firestore
  .document('Denuncias/{denunciaID}')
  .onWrite((snap, context) => {
    const doc = snap.after.data()
    const classificadoId = doc.cid
    const idTo = doc.peerId

    db.collection('Classificados').doc(classificadoId)
      .update({
        aprovado: false
      })
      .then(r => {
        getToken(idTo).then(token => {
          // sendMsg...
        })
      }).catch(updateErr => {
        console.log("updateErr: " + updateErr)
      })

    async function getToken(id) {
      let response = "getTokenResponse"
      console.log("id in getToken: " + id)
      return db.collection('users').doc(id).get()
        .then(user => {
          console.log("user in getToken: " + user.data())
          response = user.data().pushToken
        })
        .catch(e => {
          console.log("error get userToken: " + e)
          response = e
        });
      return response
    }

    return null
  });

И это из журнала консоли FB:

-1: 43: 33.906 AM Выполнение функции началось

-1: 43 : 36.799 AM Выполнение функции заняло 2894 мс, завершено со статусом: 'ok'

-1: 43: 43.797 AM id в getToken: Fm1RwJaVfmZoSgNEFHq4sbBgoEh1

-1: 43: 49.196 AM в getToken : undefined

-1: 43: 49.196 AM ошибка get userToken: TypeError: Невозможно прочитать свойство pushToken из неопределенного

-1: 43: 49.196 AM возвращенный токен: undefined

И мы можем видеть на этом скриншоте из БД, что do c действительно существует:

enter image description here

Надеюсь, кто-то может указать мне на то, что я я делаю что-то не так.

добавлен скриншот второго примера развернутого @Renaud: deployed function

1 Ответ

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

Как писал Дуг в своем комментарии, вам нужно "вернуть обещание из функции верхнего уровня, которая разрешается, когда вся работа asyn c завершена". Он также объясняет это очень хорошо в официальной серии видео: https://firebase.google.com/docs/functions/video-series/ (в частности, 3 видео под названием «Learn JavaScript Promises»). Вы обязательно должны их посмотреть, настоятельно рекомендуется!

Итак, следующие модификации вашего кода должны работать (не проверено):

exports.addDenuncia = functions.firestore
    .document('Denuncias/{denunciaID}')
    .onWrite(async (snap, context) => {   // <- note the async keyword

        try {

            const doc = snap.after.data()
            const classificadoId = doc.cid
            const idTo = doc.peerId

            await db.collection('Classificados').doc(classificadoId)
                .update({
                    aprovado: false
                });

            const userToSnapshot = await db.collection('users').doc(idTo).get();
            const token = userToSnapshot.data().pushToken;

            await sendMsg(token);  // <- Here you should take extra care to correctly deal with the asynchronous character of the sendMsg operation

            return null;  // <-- This return is key, in order to indicate to the Cloud Function platform that all the asynchronous work is done

        } catch (error) {
            console.log(error);
            return null;
        }

    });

Поскольку вы используете в своем коде функцию async, Я использовал синтаксис async/await, но мы могли бы написать его, связав обещания с помощью метода then(), как показано ниже.

Кроме того, в вашем случае я не уверен, что он добавляет любое значение, чтобы поместить код, который получает токен, в функцию (если вы не хотите вызывать его из других облачных функций, но затем вы должны удалить его из addDenuncia облачной функции). Вот почему он был заменен двумя строками кода в главном блоке try.

Версия с цепочечными обещаниями с помощью метода then()

В этой версии мы объединяем различные возвращенные обещания с помощью асинхронных методов с методом then(). По сравнению с версией async/await, приведенной выше, она очень четко показывает, что означает "возвратить обещание из функции верхнего уровня, которая разрешает, когда вся асинхронная работа завершена" .

exports.addDenuncia = functions.firestore
    .document('Denuncias/{denunciaID}')
    .onWrite((snap, context) => {   // <- no more async keyword

        const doc = snap.after.data()
        const classificadoId = doc.cid
        const idTo = doc.peerId

        return db.collection('Classificados').doc(classificadoId)  // <- we return a promise from the top level function
            .update({
                aprovado: false
            })
            .then(() => {
                return db.collection('users').doc(idTo).get();
            })
            .then(userToSnapshot => {
                if {!userToSnapshot.exists) {
                   throw new Error('No document for the idTo user');
                }
                const token = userToSnapshot.data().pushToken;

                return sendMsg(token);   // Again, here we make the assumption that sendMsg is an asynchronous function
            })
            .catch(error => {
                console.log(error);
                return null;
            })

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