【问题标题】:Google Firebase Error(Function returned undefined, expected Promise or value)Google Firebase 错误(函数返回未定义、预期的 Promise 或值)
【发布时间】:2018-04-18 02:44:12
【问题描述】:

我正在使用 Firebase 开发服务器。

我在 Youtube 上复制了 Google 开发者的视频。

效果很好,但是在日志中有错误:

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

它说函数返回undefined,但我让function 返回一个promise`set``

我该如何解决这个问题?

function sanitize(s) {
    var sanitizedText = s;
    console.log('sanitize params: ', sanitizedText);
    sanitizedText = sanitizedText.replace(/\bstupid\b/ig, "wonderful");
    return sanitizedText;
}
exports.sanitizePost = functions.database
    .ref('/posts/{pushId}')
    .onWrite(event => {
        const post = event.data.val();
        if (post.sanitized) return;

        console.log('Sanitizing new post', event.params.pushId);
        console.log(post);
        post.sanitized = true;
        post.title = sanitize(post.title);
        post.body = sanitize(post.body);
        return event.data.ref.set(post); 
    })

我是 Firebase、Nodejs 的初学者。

【问题讨论】:

  • 试试if (post.sanitized) return true;
  • @FrankvanPuffelen:这篇文章获得了很多浏览量。在 AaronJo 对我下面的回答发表的评论中,他分享了 Firebase 支持表示需要 Promise 或标量返回值的更改是故意的,并且将保持不变。您能否分享有关为什么进行更改的任何见解?有什么好处?当返回一个非 Promise 的值时,这个值有什么意义吗?
  • 当你显式返回一个值时,很明显函数完成了。当您明确返回一个承诺时,很明显该函数需要保持活动状态,直到该承诺被解决/拒绝。不返回值时,不清楚函数处于什么状态。
  • @FrankvanPuffelen firebase.google.com/docs/functions/terminate-functions 可以更新吗?它引导人们“返回”;仍然,这让我有点困惑。
  • 我看不出那个页面有什么问题,唯一的“返回”指令是“使用return; 语句终止同步函数。”,它用于同步 函数,它是正确的 afaik。这个问题是关于一个异步函数,它有一个缺少的返回值。

标签: javascript node.js firebase firebase-realtime-database google-cloud-functions


【解决方案1】:

正如弗兰克在他对您的帖子的评论中指出的那样,产生警告的返回语句是这样的:

if (post.sanitized) return;

可以通过返回一个虚拟值(例如 null、false、0)来消除警告。该值未使用。

当函数使用没有值的 return 语句退出时,早期版本的 Cloud Functions 不会报错。这就解释了为什么您在链接的视频和the documentation 中看到return;。 Firebaser Frank van Pufeelen 对这个问题的评论解释了为什么要进行更改。

按照 Frank 的建议,消除警告的最简单方法是添加返回值:

if (post.sanitized) return 0;

另一种选择是将触发器从onWrite() 更改为onCreate()。那么当帖子被清理并且不需要产生警告的检查时,该函数将不会被调用:

exports.sanitizePost = functions.database
    .ref('/test/{pushId}')
    .onCreate(event => {  // <= changed from onWrite()
        const post = event.data.val();
        //if (post.sanitized) return; // <= no longer needed

        console.log('Sanitizing new post', event.params.pushId);
        console.log(post);
        //post.sanitized = true; // <= not needed when trigger is onCreate()
        post.title = sanitize(post.title);
        post.body = sanitize(post.body);
        return event.data.ref.set(post);
    });

【讨论】:

  • 这项检查会很快被删除吗?否则,我们将不得不更改大量代码以消除日志中的错误警告。
  • @AaronJo:联系 Firebase 支持:firebase.google.com/support/contact/bugs-features
  • 从 Firebase 支持人员告诉我的情况来看,情况似乎会保持这种状态。
  • @AaronJo:感谢您分享 Firebase 支持的回复。我不清楚要求返回值有什么好处。
  • 我也不清楚。我不得不将return 0; 添加到函数的末尾,以消除此日志错误。我真的很想知道必须添加(对我而言)无关的代码行有什么好处。也许 @frank-van-puffelen 或 Firebase 团队的其他人可以解释它的逻辑?
【解决方案2】:

我在尝试使用返回承诺的.get() 读取文档时遇到了同样的错误。

我在official Firebase YouTube tutorial 中发现要解决这个错误,我需要return promise 行代码。查看教程链接视频中的分钟 4:18 [https://youtu.be/d9GrysWH1Lc]

另外,作为旁注,引导我找到教程解决方案的原因是,当我注意到函数日志中确实记录了有效值但仅在函数关闭后才记录,即使错误表明结果未定义。

【讨论】:

  • 教程链接不再有效:-/
  • 点击我输入“official Firebase YouTube tutorial”的视频的超链接
【解决方案3】:

除了@bob-snyder 所说的,您的问题是您在某种条件下返回undefined

if (post.sanitized) return;

我的建议是使用单一出口点,这是编程时的常见技巧。 Article

示例

// code...
const SUCCESS_CODE = 0;

exports.sanitizePost = functions.database
    .ref('/posts/{pushId}')
    .onWrite(event => {
        const post = event.data.val();

        let response = Promise.resolve(SUCCESS_CODE);

        if (!post.sanitized) {
            console.log('Sanitizing new post', event.params.pushId);
            console.log(post);
            post.sanitized = true;
            post.title = sanitize(post.title);
            post.body = sanitize(post.body);
            response = event.data.ref.set(post); 
        }

        return response;
    })

【讨论】:

    【解决方案4】:

    我注意到,当触发器处理程序是异步函数时,即使我们没有明确的 return 语句,也不会引发警告。

    当触发器处理程序是一个同步函数时,我们需要一个显式的 return 语句来消除警告,例如 like it was suggested 在接受的答案中。

    也就是说,如果我们重写

    exports.updatePost = functions.firestore
    .document("posts/{postId}")
    .onUpdate(async (snap, context) => { /* async handler*/
      ...
    });
    

    exports.updatePost = functions.firestore
    .document("posts/{postId}")
    .onUpdate((snap, context) => { /* sync handler*/
      ...
    });
    

    我们需要在同步处理程序中执行return 0; 或类似操作。

    无论如何,对于异步,在异步处理程序上显式返回一个承诺可能是个好主意,如advised on the official docs

    通过返回 JavaScript 承诺来解析执行异步处理的函数(也称为“后台函数”)。

    【讨论】:

      猜你喜欢
      • 2018-12-03
      • 2019-08-12
      • 1970-01-01
      • 1970-01-01
      • 2018-09-27
      • 2018-12-05
      • 2019-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多