Firestore 推送通知“超时”错误通知并不总是被发送

时间:2021-06-30 17:27:37

标签: javascript swift

我正在从我的应用程序调用一个函数,该函数向应用程序上的特定用户发送通知。大部分时间通知都会成功发送,但很多时候不会发送。当它没有被发送时,我检查日志以查看

<块引用>

函数执行耗时 60003 毫秒,完成状态为:'timeout'

我曾尝试玩我的承诺/异步等待,但没有运气,因为我怀疑这就是问题所在。

这是我的云代码现在的样子

exports.sendNotification = functions.https.onRequest(async (request, response) => {

    if (request.method !== "POST") {
        response.status(400).send("Send it using post request");
        return;
    }

    var toUid = request.body.toUid
    var fcm = request.body.fcm
    var fromUid = request.body.fromUid
    var type = request.body.type
    var fromName = request.body.fromName
    var messageText = request.body.message

    if (toUid === "" || fromUid === "" || fcm === "") {
        response.status(400).send("Parameter is missing!");
        return;
    }

    // common data for both platforms
    const notification = {
     title: fromName,
     body: messageText,
    }
    const fcmToken = fcm

    // ios specific headers
    const apns = {
      headers: {
        "apns-collapse-id": 'toUid'
      },
      payload: {
        aps: {
          sound: 'default'
        },
        "data": {
          "fromUid": fromUid,
          "type": type
        }
      }
    }

    // final message
    const message = {
     token: fcmToken,
     notification: notification,
     apns: apns,
    }

    // send message
    try {
      return await admin.messaging().send(message);
      response.status(200).send("Done");
    } catch(e) {
      console.log('Error sending message:', e);
    }
});

我从应用程序调用函数如下

         AF.request("https://myproject.net/sendNotification", method: .post, parameters: parameters, encoding: JSONEncoding.default)
         .responseString { response in
             print(response)
            DispatchQueue.main.async {
                completion("done")
            }
         }

我已经看到其他类似问题的 stackoverflow 问题,其中建议使用 .post 和 JSONEncoding.default,这就是我现在所拥有的。

2 个答案:

答案 0 :(得分:1)

来自https://firebase.google.com/docs/functions/http-events#terminate_http_functions

在您的 catch 块中没有调用 .send() 或任何等效项,因此从上面的链接:

<块引用>

总是以 send()、redirect() 或 end() 结束 HTTP 函数。否则,您的功能可能会继续运行并被系统强制终止。另请参阅同步、异步和承诺。

此外,最好在 try/catch 中将整个代码包装在 onRequest 回调中。

这是带有建议修复的代码:

exports.sendNotification = functions.https.onRequest(async (request, response) => {

  try {

    if (request.method !== "POST") {
      response.status(400).send("Send it using post request");
      return;
    }

    var toUid = request.body.toUid
    var fcm = request.body.fcm
    var fromUid = request.body.fromUid
    var type = request.body.type
    var fromName = request.body.fromName
    var messageText = request.body.message

    if (toUid === "" || fromUid === "" || fcm === "") {
      response.status(400).send("Parameter is missing!");
      return;
    }

    // common data for both platforms
    const notification = {
      title: fromName,
      body: messageText,
    }
    const fcmToken = fcm

    // ios specific headers
    const apns = {
      headers: {
        "apns-collapse-id": 'toUid'
      },
      payload: {
        aps: {
          sound: 'default'
        },
        "data": {
          "fromUid": fromUid,
          "type": type
        }
      }
    }

    // final message
    const message = {
      token: fcmToken,
      notification: notification,
      apns: apns,
    }

    // send message
    await admin.messaging().send(message); // do not return here
    response.status(200).send("Done");

  } catch (e) {
    response.status(500).send(e) // note the .send() wich terminates the request
  }
});

答案 1 :(得分:0)

无论如何,我都不是节点专家,但使用 Firebase Messaging 有一段时间并提出了一个有效的异步解决方案,以根据实时数据库中的数据创建发送通知。除了我真正看到的触发器之外,唯一的其他区别是我还没有发送特定于 APNS 的标头...

我现在还记得我在尝试使用异步 messaging.send 时遇到了间歇性超时问题,这就是我在那里使用 promise 的原因。

exports.onMessageCreate = functions.database
.ref('/users/{userId}/notifications/unread/{notificationId}')
.onCreate(async (snapshot, context) => {
    
    const message = snapshot.val()
    const category = message.category
    const title = category + ": " + message.title
    const text = message.text
    const forUserId = message.forUserId
    const date = message.date
    
    const token = await getUserToken(forUserId)
    
    if (token == null) {
        throw new functions.https.HttpsError('unavailable', 'The token is nil, unable to send message')
    }
    
    const notification = {
        notification: {
            title: title,
            body: text
        },
        data: {
            category: category,
            title: message.title,
            text: text,         
            forUserId: forUserId,
            date: date.toString()
        },
        token: token
    }
    
    return admin.messaging().send(notification)
    .then((response) => {
        console.log('Successfully sent notification:', response)
    })
    .catch((error) => {
        console.log('Error sending notification:', error)
    })
    
})