Search code examples
javascriptfirebasegoogle-cloud-functionses6-promise

Firebase Cloud Functions "Function returned undefined, expected Promise or value"


I'm trying to send a push notification via Firebase Cloud Functions to each member of a group when a new message is added. I'm not used to use Promises and need some help here.

exports.sendPushFromMessage = functions.database.ref('chats/{groupId}/messages/{msgId}').onCreate((snap, context) => {
    const groupId = context.params.groupId;
    const users = [];
    const msgTitle = 'New Message';
    const msgBody = snap.val().messageText;
    const creator = snap.val().from;
    const root = snap.ref.root;
    let messages = [];
    return root.child(`groups/${groupId}/selected`).once('value', snapshot => {
      snapshot.forEach(user => {
        root.child(`users/${user.val().uid}`).once('value', spanshot => {
          const expoToken = snapshot.val().token;
          const userId = snapshot.val().uid;
          if (expoToken && (creator !== userId)) {
            messages.push({
              "to": expoToken,
              "title": msgTitle,
              "body": msgBody
            });
          }
        })
      })
      return messages;
    }).then(messages => {
      return fetch('https://exp.host/--/api/v2/push/send', {
        method: "POST",
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json"
        },
        body: JSON.stringify(messages)
      })
    }).catch((e) => console.log(e));
  })

In the log of Firebase Functions I can see the following error:

Function returned undefined, expected Promise or value

I know the problem is probably how I'm handling the Promises. This problem has been bothering me for quite some time, it would be awesome if somebody could help me.

Here is another approach I tried:

exports.sendPushFromMessage = functions.database.ref('chats/{groupId}/messages/{msgId}').onCreate((snap, context) => {
    const groupId = context.params.groupId;
    const users = [];
    const msgTitle = 'New Message';
    const msgBody = snap.val().messageText;
    const creator = snap.val().from;
    const root = snap.ref.root;
    root.child(`groups/${groupId}/selected`).once('value', snapshot => {
      let users = [];
      snapshot.forEach(user => {
        const uid = user.val().uid;
        users.push(uid);
        console.log('fotze' + user.val().uid);
      })
      return Promise.all(users);
    })
    .then(users => {
      let messages = [];
      console.log(users);
      users.forEach(user => {
        console.log('fucking bitch: ' + user.toString());
        console.log('bitch!' + user);
        root.child(`users/${user}/`).once('value', snapshot => {
          const expoToken = snapshot.val().token;
          const userId = snapshot.val().uid;
          console.log('cunt' + snapshot.val().token);
          if (expoToken && (creator !== userId)) {
            messages.push({
                "to": expoToken,
                "title": msgTitle,
                "body": msgBody
            })
          } // if
        }); // once
      }); //forEach
      return Promise.all(messages);
    })
    .then(messages => {
      return fetch('https://exp.host/--/api/v2/push/send', {
        method: "POST",
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json"
        },
        body: JSON.stringify(messages)
      })
    }).catch((e) => console.log(e));
  })

Solution

  • Please test this way:

    exports.sendPushFromMessage = functions.database.ref('chats/{groupId}/messages/{msgId}').onCreate((snap, context) => {
      const groupId = context.params.groupId;
      const users = [];
      const msgTitle = 'New Message';
      const msgBody = snap.val().messageText;
      const creator = snap.val().from;
      const root = snap.ref.root;
      let messages = [];
      const promises = [];
      return root.child(`groups/${groupId}/selected`).once('value', snapshot => {
        snapshot.forEach(user => {
          const promise = root.child(`users/${user.val().uid}`).once('value', snapshot => {
            const expoToken = snapshot.val().token;
            const userId = snapshot.val().uid;
            if (expoToken && (creator !== userId)) {
              messages.push({
                "to": expoToken,
                "title": msgTitle,
                "body": msgBody
              });
            }
          });
          promises.push(promise);
        });
        return Promise.all(promises).then(() => {
          return sendMessages(messages);
        });
      });
    });
    
    function sendMessages(messages){
      return new Promise((resolve, reject) => {
        const f = fetch('https://exp.host/--/api/v2/push/send', {
          method: "POST",
          headers: {
            "Accept": "application/json",
            "Content-Type": "application/json"
          },
          body: JSON.stringify(messages)
        });
        f.on("end", () => {
          resolve();
        });
      });
    }