Как перестать читать child_added с помощью облачных функций Firebase?

Я пытаюсь получить все 10 записей, используя это:

exports.checkchanges = functions.database.ref('school/{class}').onCreate(snap => {

    const class=snap.params.class;

    var ref = admin.database().ref('/students')
    return ref.orderByChild(class).startAt('-').on("child_added", function(snapshot) {

        const age=snapshot.child("age");
        // do the thing

    })
)}

Проблема в том, что после того, как я правильно получаю 10 нужных мне записей, даже через несколько дней, когда добавляется новая запись, отвечающая этим условиям, эта функция все еще вызывается.

Когда я меняю on("child_added на once("child_added), я получаю только 1 запись вместо 10. И когда я меняю on("child_added to on("value я получаю ноль на это:

const age=snapshot.child("age");

Итак, как я могу предотвратить вызов функции для будущих изменений?


person user2396640    schedule 13.10.2017    source источник


Ответы (1)


При реализации взаимодействия с базой данных в Cloud Functions важно иметь детерминированное конечное условие. В противном случае среда Cloud Functions не будет знать, когда ваш код будет готов, и может либо убить его слишком рано, либо заставить его работать (и, таким образом, выставлять вам счета) дольше, чем это необходимо.

Проблема с вашим кодом заключается в том, что вы подключаете прослушиватель с помощью on, а затем никогда его не удаляете. Кроме того (поскольку on() не возвращает обещание), Cloud Functions не знает, что вы закончили. В результате ваш on() слушатель может жить бесконечно долго.

Вот почему в большинстве облачных функций, использующих базу данных реального времени, вы увидите их с использованием once(). Чтобы получить всех детей с once(), мы будем прослушивать событие value:

exports.checkchanges = functions.database.ref('school/{class}').onCreate(snap => {

    const class=snap.params.class;

    var ref = admin.database().ref('/students')
    return ref.orderByChild(class).startAt('-').limitToFirst(10).once("value", function(snapshot) {
      snapshot.forEach(function(child) {
        const age=child.child("age");
        // do the thing
      });
    })
)}

Я добавил limitToFirst(10), так как вы указали, что вам нужно всего 10 детей.

person Frank van Puffelen    schedule 13.10.2017
comment
Если я не буду limitToFirst (10), он получит все, но никогда не вернется к нему снова, пока новый onCreate не станет актуальным? - person user2396640; 13.10.2017
comment
Без limitToFirst(10) вы получите всех учащихся, соответствующих запросу, но все же только один раз для каждого нового созданного класса (потому что это то, что вы запускаете). - person Frank van Puffelen; 13.10.2017