E.Bolandian
E.Bolandian

Reputation: 573

Firebase cloud function - returned undefined,expected Promise or value

I'm trying to send a notification to a user but for some reason i have an error. The error is "Function returned undefined, expected Promise or value".

I cant understand what does this line means, hope you guys can take a look at my code and tell me where im wrong.

CODE

exports.sendNotification = functions.database.ref('/likes/{videoId}/{currentUser}').onWrite(event =>{
  console.log("Start send like notification");
  const model = event.data.val();
  let ownerVideoUserId = model.userVideoID;
  let username = model.userName;

  if(username == ""){
    username = "Somebody";
  }

  console.log("model notifi: ",model);
  console.log("userVideoID notifi: ",ownerVideoUserId);
  console.log("username notifi: ",username);

  let reference = admin.database().ref("/users/" + ownerVideoUserId);
        reference.once('value').then(snap => {
            //get the token
    let token = snap.child('token').val();
    console.log("user token: ",token);


  const payload = {
    data: {
      title: "Talent",
      message: username + " liked your video",
    }
  }

  return admin.messaging().sendToDevice(token,payload).then(function(res){
    console.log("Successfully sent message:", res);

  }).catch(function(error) {
    console.log("Error sending message:", error);
    });

   })
});

Can you spot my mistake?

EDIT exports.sendCommentNotification = functions.database.ref('genresComments/{genre}/{videoId}/{userId}').onWrite(event =>{ console.log("Start send comment notification"); const model = event.data.val(); let ownerVideoUserId = model.ownerVideoID; let username = model.userName;

    if(username == "")
      username = "Somebody";


    console.log("model: ",model);
    console.log("userVideoID: ",ownerVideoUserId);
    console.log("username: ",username);

      let reference = admin.database().ref("/users/" + ownerVideoUserId);
    return reference.once('value').then(snap => {
      //get the token
      let token = snap.child('token').val();
      console.log("user token: ",token);


    const payload = {
      data: {
        title: "Talent",
        message: username + " comment your post",
      }
    }

    return admin.messaging().sendToDevice(token,payload).then(function(res){
      console.log("Successfully sent message:", res);

    }).catch(function(error) {
      console.log("Error sending message:", error);
      });

   }).catch(function(error){
     console.log("Error with the reference:",error);

   }).then(()=>{
    console.log('notification');
  });
 });

Upvotes: 1

Views: 1035

Answers (2)

JeremyW
JeremyW

Reputation: 5272

As the error message hints, you aren't returning anything from the parent-level function... which is a problem for cloud functions. If you're going to be calling asynchronous code, like the ref.once('value') method, then you need to return that.

exports.sendNotification = functions.database.ref('/likes/{videoId}/{currentUser}').onWrite(event =>{
    console.log("Start send like notification");
    const model = event.data.val();
    let ownerVideoUserId = model.userVideoID;
    let username = model.userName;

    if(username == ""){
        username = "Somebody";
    }

    console.log("model notifi: ",model);
    console.log("userVideoID notifi: ",ownerVideoUserId);
    console.log("username notifi: ",username);

    let reference = admin.database().ref("/users/" + ownerVideoUserId);

    return reference.once('value').then(snap => {      // <----- RETURN NEEDED HERE
        //get the token
        let token = snap.child('token').val();
        console.log("user token: ",token);

        const payload = {
            data: {
                title: "Talent",
                message: username + " liked your video",
            }
        }

        return admin.messaging().sendToDevice(token,payload).then(function(res){
            console.log("Successfully sent message:", res);
        }).catch(function(error) {
            console.log("Error sending message:", error);
        });

    })
});

EDIT:

Definitely recommend you check out the video series Renaud recommends in his answer. Very good explanations in there.

Upvotes: 3

Renaud Tarnec
Renaud Tarnec

Reputation: 83048

As you will see in the three videos from Doug Stevenson about "JavaScript Promises" from the Firebase video series (https://firebase.google.com/docs/functions/video-series/) you MUST return a Promise or a value in your Cloud Function, to indicate to the platform that it has completed.

So, in your case you may do as follows (if you don't care about the console logging):

exports.sendNotification = functions.database.ref('/likes/{videoId}/{currentUser}').onWrite(event =>{
  ....

  let reference = admin.database().ref("/users/" + ownerVideoUserId);
  return reference.once('value')
  .then(snap => {
     ...
     return admin.messaging().sendToDevice(token,payload);
  });
});

or as follows if you want to keep the console logging:

...
  let reference = admin.database().ref("/users/" + ownerVideoUserId);

  return reference.once('value')
  .then(snap => {
  return admin.messaging().sendToDevice(token,payload);
  .then(function(res){
    console.log("Successfully sent message:", res);
    return null;
  })
  .catch(function(error) {
    console.log("Error sending message:", error);
    return null;
  });
...

Upvotes: 3

Related Questions