Ich versuche einen Benachrichtigungsserver in node.js zu erstellen, der die Benachrichtigungen von einer Datenbank erhält, ihre Nutzdaten bearbeitet, sie über Firebase Cloud Messaging sendet und dann ihren Status bearbeitet in der Datenbank.Programm wird nicht beendet wenn Firebase Cloud Messaging gesendet wird sendToDevice
Javascript ist nicht meine Hauptsprache, also hoffe ich, dass es in diesem Code nicht viele Missverständnisse gibt.
Um dies zu tun, verwende ich einige Promises und ein Promise.all.
Derzeit ist das Problem, wenn ich firebase.admin.messaging().sendToDevice
aufrufen, beendet meine App nie die Ausführung. Hier
ist der Code:
main.js:
'use strict';
global.basePath = __dirname + '/';
const conf = require('./config/config'),
db = require('./lib/database'),
builder = require('./notify/builder');
const gender = conf.genderId[process.argv[2]],
type = conf.typeId[process.argv[3]],
confSql = conf.inc.prod ? conf.mysql.prod : conf.mysql.dev,
database = new db.database(confSql);
const notify = new Promise(
(resolve, reject) => {
if (typeof(gender) !== 'number' && typeof(type) !== 'number') {
return reject('Error: gender and type are mandatory');
}
resolve();
}
);
function main() {
notify
//Get the notifications from DB - They are already group by user
.then(() => { return database.getNotifications(gender, type); })
//Set the payload, send to Firebase, and update the status in DB
// <-- Inside it is the call to Firebase
.then(rows => { return Promise.all(rows.map(builder.handleNotification)); }
, err => {
return database.close().then(() => {
return Promise.reject(err)
});
}
)
.then(() => {
console.log('Success ! The DB and the app must close.');
database.close();
})
.catch(console.log.bind(console))
;
}
main();
builder.js:
'use strict';
const conf = require('./../config/config'),
sender = require('./sender'),
database = require('./../lib/database');
//This is called inside an array.map
//It is a chain of Promises that are resolved or rejected in a Promise.all
function handleNotification(notification){
let notif = notification;
return Promise.resolve(setGroupPayload(notification))
.then(sender.send)
.then(console.log)
.catch(error => {
return Promise.reject(error);
});
}
function setGroupPayload (notification){
//Do some change on notifications
// (...)
return notification;
}
module.exports = {
handleNotification: handleNotification
};
database.js:
const mysql = require('mysql');
function Database(config) {
this.connection = mysql.createConnection(config);
}
Database.prototype.query = function query(sql, args) {
return new Promise((resolve, reject) => {
this.connection.query(sql, args, (err, rows) => {
if (err)
return reject(err);
resolve(rows);
});
});
};
Database.prototype.ping = function ping(){
return new Promise((resolve, reject) => {
this.connection.ping(err => {
if (err)
return reject(err);
resolve('Server responded to ping');
});
});
};
Database.prototype.close = function close() {
console.log('close connection');
return new Promise((resolve, reject) => {
this.connection.end(err => {
if (err)
return reject(err);
console.log('connection closed');
resolve();
});
});
};
Database.prototype.getNotifications = function getNotifications (gender, type) {
const query = `(...)`;
const params = [gender, type];
return this.query(query, params);
};
module.exports = {
database: Database
};
Und schließlich die sender.js:
'use strict';
const firebase = require('./../lib/firebase-admin');
/**
*
* @param notification
* @returns {Promise}
*/
function send (notification) {
if (notification.message === false) {
return Promise.reject(["payload is empty"]);
}
if (!(notification.token && notification.token.length > 0)) {
return Promise.reject(["target is empty."]);
}
const options = {
contentAvailable: true
};
//When this is called here, the app never ends
return firebase.admin.messaging().sendToDevice(notification.token, notification.message, options);/
}
module.exports = {
send: send
};
Ich habe von firebase.admin.messaging().sendToDevice(notification.token, notification.message, options)
die folgende Antwort, die eine Promise.resolve:
[ { error: { [Error: The provided registration token is not registered. A previously valid registration token can be unregistered for a variety of reasons. See the error documentation for more details. Remove this registration token and stop using it to send messages.] errorInfo: [Object], codePrefix: 'messaging' } } ]
Das ist richtig, weil das Token nicht gültig ist. Und ich möchte mit dieser Antwort umgehen. Aber was ich nicht verstehe, warum hört meine App nie auf? Es sieht so aus, als wären sie im Promise ein unendliches Versprechen. Alle verhindern, dass die App beendet wird.
Ich habe auch versucht die Antwort von Firebase zu handhaben und eine Promise.reject
an die Versprechen Kette senden, aber ohne Erfolg ...
So ... Wo bin ich falsch? Vielen Dank an alle, die mir helfen können, diesen Fehler zu beheben.
Edit:
Ich habe eine .then()
vor dem Fang in der builder.js
hinzugefügt, wie @JimWright gefragt.
Und hier ist das Ergebnis:
Hier ist das Ergebnis:
{ results: [ { error: [Object] } ],
canonicalRegistrationTokenCount: 0,
failureCount: 1,
successCount: 0,
multicastId: 6057186106180078000 }
Success ! The DB and the app must close.
close connection
connection closed
Try a 'dann()' vor dem Fang in 'builder.js' Zugabe - erhalten Sie das Ergebnis da? Protokollieren Sie den Fehler auch, um zu sehen, ob Sie dort etwas erhalten. –
Ist das von 'then()' oder 'catch()'? –
Vielen Dank für Ihre Antwort @JimWright. Ich habe den Beitrag bearbeitet. sendToDevice sendet eine Promise.resolve(). Auch wenn es einen Fehler sendet, ist es immer noch eine Lösung. – MrZog