There is a list of cities - further messages (all messages) and further a list of users of this city 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" } } } } 

We use the functions.database.ref ('/ {city} / messages / {msgID}') method. OnWrite ... track when a new message arrives

And then our task is to send a push notification using the method admin.messaging (). SendToDevice (tokens, payload)

But for this we need to collect all tokens of user devices, and here I have a problem.

It is impossible to go through the loop in the database and collect all the tokens. What is wrong with the function?

My code on 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; } 

    1 answer 1

    Here is the work function, it is on the chat of the project firebase-info.com translated into Russian for you.

     // Импортируем 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); }) ; } }) ; }) ; 
    • thank! the error was in fact, in that the cities were written in Russian Cyrillic, and the firebase went to an empty place in the database. it is also better to use the forEach loop (not for (var property in data)) as you have in response - Bogdan Bystritskiy