Firebase云函数总是超时

16

我正在探索Firebase云函数,并试图通过HTTP请求发送通知。

问题是,即使我成功发送了通知,请求也总是超时。

以下是我的脚本:

/functions/index.js

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp(functions.config().firebase);

exports.friendRequestNotification = functions.https.onRequest((req, res) => {

    const senderId = req.query.senderId;
    const recipientId = req.query.recipientId;
    const getRecipientPromise = admin.database().ref(`/players/${recipientId}`).once('value');
    const getSenderPromise = admin.database().ref(`/players/${senderId}`).once('value');

    return Promise.all([getRecipientPromise, getSenderPromise]).then(results => {

        const recipient = results[0];
        const sender = results[1];

        const recipientToken = recipient.child("notificationsInfo/fcmToken").val();
        const notificationAuthorization = recipient.child("notificationsInfo/wantsToReceiveNotifications").val();
        const recipientBadge = recipient.child("notificationsInfo/badgeNumber").val();
        const senderUsername = sender.child("username").val();

        const payload = {
            notification: {
              title: `FriendRequest`,
              body: `You have a new friend request from ${senderUsername}!`,
              badge: (recipientBadge+1).toString()
            }
        };

        if (notificationAuthorization) {

            return admin.messaging().sendToDevice(recipientToken, payload).then(response => {

            });

        }

        return admin.database().ref(`/players/${recipientId}/notificationsInfo/badgeNumber`).setValue(recipientBadge+1);

    });

});

此外,似乎badgeNumber从未更新过,这与超时问题有关吗?


4
对于可能会看到这篇文章的其他人,请记住,向第三方发送HTTPS请求需要您拥有付费Firebase帐户;在免费帐户上无法发送到Google以外的HTTP请求,以防止滥用。 - Kato
哦,我明白了,你在哪里找到这个信息的?数据库触发器呢? - Gnamm
1
在 Firebase 定价页面上,脚注 3 表示:“Spark 计划仅允许对 Google 拥有的服务进行出站网络请求。在 Blaze 计划中,Cloud Functions 提供了一个永久的免费层。”https://firebase.google.com/pricing/ - Doug Stevenson
2个回答

25

基于 HTTP 触发的云函数与 Express 应用一样 - 您需要使用响应对象 (res) 在请求完成时发送某些内容。在这种情况下,您可以尝试以下操作:

return Promise.all([
  /* ... */
]).then(() => {
  res.status(200).send('ok');
}).catch(err => {
  console.log(err.stack);
  res.status(500).send('error');
});

请在 Firebase 文档中查看更多详细信息:https://firebase.google.com/docs/functions/http-events#terminate_http_functions - Valentin

3

@Michael Bleigh的回答已经完全符合这个问题,让我为未来的用户增加更多信息。

根据Firebase文档:

使用以下推荐方法来管理您的函数的生命周期:

  • 通过返回JavaScript Promise解决执行异步处理(也称为“后台函数”)的函数。

  • 使用 res.redirect()res.send()res.end() 终止HTTP函数。(这是本题的情况。)

  • 使用 return; 语句终止同步函数。

注意 管理函数生命周期以确保其正确解决很重要。通过正确终止函数,您可以避免函数过长或无限循环而导致的过度收费。同时,您还可以确保运行您的函数的Cloud Functions实例在函数成功达到其终止条件或状态之前不会关闭。

  • 您需要付费计划(Blaze,按使用量付费)才能访问外部API。

如果未配置计费帐户,则可能会在Firebase函数日志中看到以下警告:

未配置计费帐户。无法访问外部网络且配额严重受限。请配置计费帐户以消除这些限制。

查看此链接获取更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接