0

I am writing a firebase function using TypeScript to send push notifications to multiple users. But when I run firebase deploy --only functions command, TSLint gives an error "Promises must be handled appropriately".

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp(functions.config().firebase);

export const broadcastJob = functions.https.onRequest((request, response) => {
    const db = admin.firestore();
    db.collection('profiles').get().then(snapshot => {
        snapshot.forEach(doc => {
            const deviceToken = doc.data()['deviceToken'];
            admin.messaging().sendToDevice(deviceToken, { //<-- Error on this line
                notification: {
                    title: 'Notification',
                    body: 'You have a new notification'
                }
            });
        });
        response.send(`Broadcasted to ${snapshot.docs.length} users.`);
    }).catch(reason => {
        response.send(reason);
    })
});
Ali Shahzad
  • 5,163
  • 7
  • 36
  • 64

1 Answers1

0

First a remark, I think you are better of using a callable function instead of onRequest. See: Are Callable Cloud Functions better than HTTP functions?

Next, you need to wait for your asynchronous functions to finish before sending back the response.

In this case you are looping through all your documents returned from the query. For each document you call sendToDevice. This means you are executing multiple async functions in parallel.

You can use:

Promise.all([asyncFunction1, asyncFunction2, ...]).then(() => {
 response.send(`Broadcasted to ${snapshot.docs.length} users.`);
});

The following code is not tested:

export const broadcastJob = functions.https.onRequest((request, response) => {
    const db = admin.firestore();
    db.collection('profiles').get().then(snapshot => {
        Promise.all(snapshot.docs.map(doc => {
            const deviceToken = doc.data()['deviceToken'];
            return admin.messaging().sendToDevice(deviceToken, {
                notification: {
                    title: 'Notification',
                    body: 'You have a new notification'
                }
            });
        })).then(() => {
         response.send(`Broadcasted to ${snapshot.docs.length} users.`);
        }
    }).catch(reason => {
        response.send(reason);
    })
});

Note that I don't use the snapshot.forEach function.

Instead I prefer to use the snapshot.docs property which contains an array of all documents returned by the query and provides all normal array functions such as 'forEach' but also 'map' which I've used here to convert an array of documents into an array of promises.

ThdK
  • 9,916
  • 23
  • 74
  • 101