我正在从我的应用程序调用一个函数,该函数向应用程序上的特定用户发送通知。大部分时间通知都会成功发送,但很多时候不会发送。当它没有被发送时,我检查日志以查看
<块引用>函数执行耗时 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,这就是我现在所拥有的。
答案 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)
})
})