1
votes

I've defined a Firebase cloud function that executes upon realtime database onCreate trigger. The function performs it's intended algorithm perfectly except that the logs always show the error: Function returned undefined, expected Promise or value. I've already tried so many things, but I still can't get that error to go away. The important snippets of the code is below.

I've already properly returned a promise. Any ideas how to make the error go away?

index.js

const sendNotificationMessageModule = require('./sendNotificationMessage');

exports.sendNotificationMessage = functions.database.ref( '/Notifications/{pushId}').onCreate((snapshot, context) => {
  sendNotificationMessageModule.sendNotificationMessage(snapshot, context, db, admin);
});

sendNotificationMessage.js

First parts of the code:

exports.sendNotificationMessage = function(snapshot, context, db, admin) {
.
.
.

Last parts of the code:

        if(...) {
        .
        .
        .
          var androidNode = {};
          androidNode[constants.propertyNotificationString] = notificationNode;
          message[constants.propertyAndroidString] = androidNode;

          return admin.messaging().send(message)
          .then((response) => {
            console.log('Successfully sent message:', response);
            return snapshotNotificationMessage.ref.remove();
          })
          .catch((error) => {
            console.log('Error sending message:', error);
          });
        }

As you can see, the message was successfully sent, but the error is still there. And of course, the data in the realtime database was also successfully removed.

cloud function error

2
When posting code, please post the entire function, not just the function body. It's very important to see what sort of cloud function it is. - Doug Stevenson
Hi, I watched your videos! They are so helpful in understanding promises. I didn't post the entire code because it is so long! So I just posted the end part of it. The function is a realtime database trigger onCreate, it successfully executes the send message, but the functions still exits with the error above. I'm posting the first and last parts now. - Poly Bug

2 Answers

2
votes

Cloud Functions for Firebase triggered by events in the background must return a promise (or in certain cases a value, e.g. return false;).

Since admin.messaging().send() returns a promise (see doc), you just have to return this promise, as follows:

var androidNode = {};
androidNode[constants.propertyNotificationString] = notificationNode;
message[constants.propertyAndroidString] = androidNode;
....
return admin.messaging().send(message);
})
.catch((error) => {
    console.log('Error sending message:', error);
    return false;
});

However, you are also calling snapshotNotificationMessage.ref.remove();, which also returns a promise. Therefore you should chain these promises in your Cloud Function. This should probably be done as follows but without your full code it is difficult to guarantee that this is 100% correct. If you add to your question your entire code, we may adapt it.

....
    var androidNode = {};
    androidNode[constants.propertyNotificationString] = notificationNode;
    message[constants.propertyAndroidString] = androidNode;
    return snapshotNotificationMessage.ref.remove();
.then(() => {
    return admin.messaging().send(message);
})
.catch((error) => {
    console.log('Error sending message:', error);
    return false;
});

In addition, I suggest you watch these two videos from the Firebase team, which explain why and how to return a promise:

https://www.youtube.com/watch?v=7IkUgCLr5oA

https://www.youtube.com/watch?v=652XeeKNHSk

The first one is more about HTTP Functions that are triggered through an HTTP request (so not with a background event) while the second is focused on background event triggered Functions, but it is advised to watch the first one before watching the second one.

1
votes

You will return to return the promise returned by sendNotificationMessage. That's how Cloud Functions knows when all async work is done:

const sendNotificationMessageModule = require('./sendNotificationMessage');

exports.sendNotificationMessage = functions.database.ref( '/Notifications/{pushId}').onCreate((snapshot, context) => {
  return sendNotificationMessageModule.sendNotificationMessage(snapshot, context, db, admin);
});