Как пробежаться по всем нужным key в Firebase Database?

220
16 декабря 2017, 08:28

Есть список городов - далее messages (все сообщения) и далее список пользователей этого города users

{ "Ижевск" : {
    "messages" : {
      "-L-HZZkAurZ0l5VTUOjD" : {
        "MediaType" : "TEXT",
        "date" : "18:54",
        "senderId" : "687",
        "senderName" : "Александр Александрович",
        "text" : "Ижевск привет",
        "token" : "dWg66sXaXHw:APA91bHXXAhzW8a7NThGBrWTjlIiukx1oqbVV6XAT"
      }
    },
    "users" : {
      "Александр Александрович" : {
        "isNotificationsEnabled" : true,
        "platform" : "android",
        "token" : "dWg66sXaXHw:APA91bHXXAhzW8a7NThGBrWTjlIiukx1oqbVV6XAT"
      },
      "Петя Александрович" : {
        "isNotificationsEnabled" : true,
        "platform" : "ios",
        "token" : "dWg66sXaXHw:APA91bHXXAhzW8a7NThGBrWTjlIiukx1oqbVV6XAT"
      }
    }
  }
}

Мы с помощью метода functions.database.ref('/{city}/messages/{msgID}').onWrite … отслеживаем когда пришло новое сообщение

И далее наша задача отправить пуш уведомление с помощью метода admin.messaging().sendToDevice(tokens, payload)

Но для этого мы должны собрать все токены устройств пользователей, и здесь у меня проблема.

Не получается пройтись в цикле по базе и собрать все токены. Что не так с функцией?

Мой код на Node.JS

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

var city = "";
exports.sendFollowerNotification = functions.database.ref('/{city}/messages/{msgID}').onWrite(event => {
  var eventSnapshot = event.data;
  //текст сообщения
  var textMsg = eventSnapshot.child("text").val();
  //имя отправителя
  var senderName = eventSnapshot.child("senderName").val();
  //токен отправителя, чтобы потом его исключить
  var tokenOfSender = eventSnapshot.child("token").val();
  //получаем город в котором было отправлено сообщение
  var cityTemp = (event.data.ref.toString().split('/'))[3];
  city = cityTemp; //записываем в глобальную переменную

  //дальше начинаются проблемы
  return loadUsers().then(users => {
          let tokens = [];
          for (let user of users) {
              tokens.push(user.token);
          }
          console.log('TOKENSARRAY = ' + tokens); // = null
          let payload = {
              notification: {
                  title: 'Сообщние от ' + senderName + ':',
                  body: textMsg,
                  sound: 'default',
                  badge: '1'
              }
          };
          return admin.messaging().sendToDevice(tokens, payload);
      });
  });

  function loadUsers() {
      let dbRef = admin.database().ref('/' + city + '/users');
      let defer = new Promise((resolve, reject) => {
          dbRef.once('value', (snap) => {
              let data = snap.val(); // = null, и дальше логично, что ничего не выйдет по задумке
              let users = [];
              for (var property in data) {
                  users.push(data[token]);
              }
              resolve(users);
          }, (err) => {
              reject(err);
          });
      });
      return defer;
  }
Answer 1

Вот рабочая функция, стоит на чате проекта firebase-info.com спецом перевел на русский для вас.

// Импортируем Firebase SDK для облачных функций
const functions = require('firebase-functions');
// Импортируем и инициализируем Firebase Admin SDK.
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// Добавляем сообщение которое приветствует нового пользователя в чате
exports.addWelcomeMessages = functions.auth.user().onCreate(event = > {
    const user = event.data;
console.log('Новый пользователь зарегистрировался в чате');
const fullName = user.displayName || 'Аноним';
// Сохраняет сообщение в базу данных -> веб приложение слышет это и отображает сообщение
return admin.database().ref('messages').push({
    name: 'Бот firebase-info.com',
    photoUrl: '/images/k-logo.png',
    text: `${fullName} зарегистрировался в чате! Приветствуем`
});
})
;

// Отбравляем пуш уведомление всем пользователя о новом сообщении в чате
exports.sendNotifications = functions.database.ref('/messages/{messageId}').onWrite(event = > {
    const snapshot = event.data;
// Отправляем пуш уведомление только в случае если новое сообщение было создано
if (snapshot.previous.val()) {
    return;
}
// Детали пуш уведомления
const text = snapshot.val().text;
const payload = {
    notification: {
        title: `${snapshot.val().name} опубликовал ${text ? 'сообщение' : 'изображение'}`,
        body: text ? (text.length <= 100 ? text : text.substring(0, 97) + '...') : '',
        icon: snapshot.val().photoUrl || '/images/profile_placeholder.png',
        click_action: `https://${functions.config().firebase.authDomain}`
    }
};
// Берем список fcm токенов девайсов.
return admin.database().ref('fcmTokens').once('value').then(allTokens = > {
    if(allTokens.val()
)
{
    // Листаем все токены
    const tokens = Object.keys(allTokens.val());
    // Отправляем сообщение ко всем токенам
    return admin.messaging().sendToDevice(tokens, payload).then(response = > {
        // Для каждого сообщения проверь была ли ошибка
        const tokensToRemove = [];
    response.results.forEach((result, index) = > {
        const error = result.error;
    if (error) {
        console.error('Ошибка отправления пуш уведомления', tokens[index], error);
        // Удаляем токены которые более не зарегистрированы
        if (error.code === 'messaging/invalid-registration-token' ||
            error.code === 'messaging/registration-token-not-registered') {
            tokensToRemove.push(allTokens.ref.child(tokens[index]).remove());
        }
    }
})
    ;
    return Promise.all(tokensToRemove);
})
    ;
}
})
;
})
;
READ ALSO
Как ограничить ширину canvas, fengyuanchen/cropper canvas size

Как ограничить ширину canvas, fengyuanchen/cropper canvas size

У меня открывается фотография в модальном окне, она открывается как canvasПроблема в том что Рамочка для вырезания может выходить за пределы...

203
Найти ближайший элемент на странице

Найти ближайший элемент на странице

Добрый день, помогите найти ближайший элемент на странице с помощью JavaScriptСейчас у меня находит ближайший элемент только по X

178