FCM og Typescript Async Await: Nettverk tidsavbrudd
Jeg er ny på Typescript og prøver å bruke async- og await-funksjonaliteten. Jeg får noen FCM-nettverkstidsavbrudd av og til, og jeg tror det har å gjøre med at jeg ikke returnerer løftene mine riktig.
Her er min skyfunksjon for å sende en push-varsling. De to funksjonene som bruker await-nøkkelordet er incrementBadgeCount og sendPushNotification:
export const pushNotification = functions.firestore
.document('company/{companyId}/message/{messageId}/chat/{chatId}')
.onCreate(async event => {
const message = event.data.data();
const recipients = event.data.data().read;
const messageId = event.params.messageId;
const ids = [];
for (const key of Object.keys(recipients)) {
const val = recipients[key];
if (val === false) {
ids.push(key);
}
}
return await Promise.all(ids.map(async (id) => {
const memberPayload = await incrementBadgeCount(id);
const memberBadgeNumberString =
memberPayload.getBadgeCount().toString();
const senderName = message.sender.name;
const senderId = message.sender.id;
const senderMemberName = message.senderMember.name;
const toId = message.receiver.id;
const text = message.text;
const photoURL = message.photoURL;
const videoURL = message.videoURL;
const dealId = message.dealId;
const dealName = message.dealName;
const payload = {
notification: {
title: `${senderName}`,
click_action: 'exchange.booth.message',
sound: 'default',
badge: memberBadgeNumberString
},
data: { senderId, toId, messageId }
};
const options = {
contentAvailable: true
}
........
const deviceIDs = memberPayload.getDeviceID()
return await sendPushNotification(id, deviceIDs, payload, options);
}));
});
Her er incrementBadgeCount-funksjonen som øker antallet merker for nyttelasten og returnerer litt informasjon for nyttelasten:
async function incrementBadgeCount(memberID: string):
Promise<MemberPushNotificaitonInfo> {
const fs = admin.firestore();
const trans = await fs.runTransaction(async transaction => {
const docRef = fs.doc(`member/${memberID}`);
return transaction.get(docRef).then(doc => {
let count: number = doc.get('badgeCount') || 0;
const ids: Object = doc.get('deviceToken');
transaction.update(docRef, {badgeCount: ++count});
const memberPayload = new MemberPushNotificaitonInfo(count, ids);
return Promise.resolve(memberPayload);
});
});
return trans
}
Og til slutt sendPushNotification-funksjonen som grensesnitt mot FCM og sender nyttelasten samt rydder opp dårlige enhetstokener:
async function sendPushNotification(memberID: string, deviceIDs: string[], payload: any, options: any) {
if (typeof deviceIDs === 'undefined') {
console.log("member does not have deviceToken");
return Promise.resolve();
}
const response = await admin.messaging().sendToDevice(deviceIDs, payload, options);
const tokensToRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
const success = result.messageId;
if (success) {
console.log("success messageID:", success);
return
}
if (error) {
const failureDeviceID = deviceIDs[index];
console.error(`error with ID: ${failureDeviceID}`, error);
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
const doc = admin.firestore().doc(`member/${memberID}`);
tokensToRemove.push(doc.update({
deviceToken: {
failureDeviceID: FieldValue.delete()
}
}));
}
}
});
return Promise.all(tokensToRemove);
}
Jeg ville sette pris på litt hjelp med å stramme opp denne Typescript-en :)
Svar #1
Sannsynligvis er det en funksjon du kaller på Firebase API som burde awaites, men som ikke blir det. Jeg er ikke kjent med Firebase for å kunne fortelle deg nøyaktig hvilken det er, men det ser ut til at alle kall til Firebase API potensielt kan awaites.
Dette er stedet hvor det å sørge for at du har type-definisjoner installert for Firebase og bruker en god editor kommer inn. Ta en titt på alle dine Firebase-kall og sørg for at ingen av dem i hemmelighet returnerer et løfte.
Du bør også sørge for at alle funksjonene og variablene dine er så sterkt typet som mulig, siden dette vil hjelpe deg med å unngå problemer.
Så, de følgende linjene ser mistenkelige ut for meg:
fs.doc(`member/${memberID}`);
transaction.update(docRef, {badgeCount: ++count});
const doc = admin.firestore().doc(`member/${memberID}`);
Svar #2
Dette er fordi du åpner for mange HTTP-tilkoblinger for å sende push-varsler, ideelt sett bør du lage en batch på 5, 10 ... for å sende push.
Prøv å endre,
return await Promise.all(ids.map(async (id) => { ... });
til,
while(ids.length) {
var batch = ids.splice(0, ids.length >= 5 ? 5 : ids.length);
await Promise.all(batch.map( async (id) => { ... });
}
