Firebase 云函数 - 返回未定义、预期的 Promise 或值

Posted

技术标签:

【中文标题】Firebase 云函数 - 返回未定义、预期的 Promise 或值【英文标题】:Firebase cloud function - returned undefined,expected Promise or value 【发布时间】:2019-08-06 18:32:23 【问题描述】:

我正在尝试向用户发送通知,但由于某种原因我遇到了错误。 错误是“函数返回未定义、预期的 Promise 或值”。

我不明白这行是什么意思,希望你们看看我的代码并告诉我我哪里错了。

代码

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);
    );

   )
);

你能看出我的错误吗?

编辑 export.sendCommentNotification = functions.database.ref('genresComments/genre/videoId/userId').onWrite(event => console.log("开始发送评论通知"); 常量模型 = event.data.val(); 让 ownerVideoUserId = model.ownerVideoID; 让用户名 = 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');
  );
 );

【问题讨论】:

【参考方案1】:

正如您将在 Doug Stevenson 的三个关于 Firebase 视频系列 (https://firebase.google.com/docs/functions/video-series/) 中的“javascript Promises”的视频中看到的那样,您必须在您的 Cloud Function 函数中返回一个 Promise 或一个值,以向平台表明它具有完成。

因此,在您的情况下,您可以执行以下操作(如果您不关心控制台日志记录):

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);
  );
);

如果您想保留控制台日志记录,则如下所示:

...
  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;
  );
...

【讨论】:

【参考方案2】:

正如错误消息提示的那样,您没有从父级函数返回任何内容......这对于云函数来说是一个问题。如果您要调用异步代码,例如 ref.once('value') 方法,那么您需要返回它。

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);
        );

    )
);

编辑:

绝对建议您查看 Renaud 在他的回答中推荐的视频系列。里面的解释很好。

【讨论】:

我已根据您的回答编辑了我的代码。一方面在 logcat 中它成功工作,但另一方面它仍然向我显示相同的错误

以上是关于Firebase 云函数 - 返回未定义、预期的 Promise 或值的主要内容,如果未能解决你的问题,请参考以下文章

函数返回未定义、预期的 Promise 或值 Firebase 日志错误

函数返回未定义,预期Promise或值和通知长时间延迟

Firebase 函数在本地提供时未返回预期的环境配置

函数以状态完成:'ok',但控制台日志显示函数返回未定义、预期的 Promise 或值

Firebase 云函数对象可能“未定义”

firebase 云函数无法读取未定义的属性“ref”