未收到 Firebase 功能云消息通知
Firebase functions cloud messaging notification not being recieved
当我从 Firebase 云消息控制台发送通知时,我的设备可以毫无问题地接收它,但是当我通过云函数发送它时,函数日志显示它已成功发送但我的设备没有收到它.我尝试切换到类型脚本,以不同的条件发送通知,但没有任何效果。该应用程序是用 flutter 编写的。
我的函数代码:
exports.sendNotification = functions.https.onRequest((request, response) => {
const db = admin.firestore();
const fcm = admin.messaging();
db.collection("users")
.where("bananas", "==", 1666).get().then(
(result) => {
if (result.size > 0) {
result.forEach((doc) => {
const payload = {
token: doc.data().NotToken,
notification: {
title: "iam a notification",
body: "Yay",
icon: "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/231/among-us-player-white-512.png",
},
};
fcm.send(payload).then((response) => {
// Response is a message ID string.
console.log("Successfully sent message: "+
doc.data().NotToken+ " ", response);
return {success: true};
}).catch((error) => {
return {error: error.code};
});
});
}
});
response.send("Notification sent !");
functions.logger.info("Notification sent!");
return null;
});
云日志
有什么想法吗?
您是否注意到您的代码从未记录此消息?
Successfully sent message
那是因为从 Firestore 加载和通过 Cloud Messaging 发送消息都是异步调用。因此,您的 response.send("Notification sent !")
在从数据库中检索数据之前运行,此时 Cloud Functions 会终止您的代码,以防止在您说完后收费。
如果您的代码中有异步操作,您需要 return 来自代码顶层的承诺,即 resolves/rejects 当所有异步代码完成时。因此,在您的情况下,这意味着只有在您从 Firestore 加载数据并发送消息后,promise 才应该解析。
让我们从一个简单的例子开始。假设您只想发送一条消息,无论数据库中有多少文档。
exports.sendNotification = functions.https.onRequest((request, response) => {
const db = admin.firestore();
const fcm = admin.messaging();
return db.collection("users") // Add return here
.where("bananas", "==", 1666).get().then((result) => {
if (result.size > 0) {
const doc = result.docs[0]; // Get the first result
const payload = {
token: doc.data().NotToken,
notification: {
title: "iam a notification",
body: "Yay",
icon: "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/231/among-us-player-white-512.png",
},
};
return fcm.send(payload).then((response) => { // Add return here
console.log("Successfully sent message: "+
doc.data().NotToken+ " ", response);
response.send("Notification sent !"); // Move this call here
return {success: true};
}).catch((error) => {
// TODO: Send an error back to the caller
return {error: error.code};
});
}
});
});
所以顶级代码现在 return 是从 Firestore 加载数据的结果,在那里,我们 return 调用 FCM,然后又 returns return {success: true};
。当 returning 承诺时,结果会冒泡 - 因此您通常可以只保留 returning 嵌套结果。
您也不会认为我们已将 response.send
移动到调用 FCM 后运行的代码中,因为我们不想在 FCM 调用完成之前将结果发送回调用方.
以上是简单的变体,因为在现实中你有多个文档,而且只有在所有文档都完成后你才完成。
为此,我们将使用 Promise.all()
,它接受一系列承诺,并在所有这些承诺都解决后解决。因此,我们将捕获对 FCM 的所有调用(return 是一个承诺)并将它们收集在一个数组中,然后我们将其传递给 Promise.all()
.
exports.sendNotification = functions.https.onRequest((request, response) => {
const db = admin.firestore();
const fcm = admin.messaging();
return db.collection("users")
.where("bananas", "==", 1666).get().then((result) => {
if (result.size > 0) {
let promises = [];
result.forEach((doc) => {
const payload = {
token: doc.data().NotToken,
notification: {
title: "iam a notification",
body: "Yay",
icon: "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/231/among-us-player-white-512.png",
},
};
promises.push(fcm.send(payload))
});
return Promise.al(promises).then((results) => {
console.log("Successfully sent messages");
response.send("Notification sent !");
return {success: true};
});
}
});
});
虽然一次要理解很多东西,但处理异步行为在 terminating functions, in this video series on Learn JavaScript Promises with Cloud Functions 上的 Firebase 文档和相当多的教程中有很好的介绍 - 所以我建议花一些时间关于那些掌握异步代码的人。
当我从 Firebase 云消息控制台发送通知时,我的设备可以毫无问题地接收它,但是当我通过云函数发送它时,函数日志显示它已成功发送但我的设备没有收到它.我尝试切换到类型脚本,以不同的条件发送通知,但没有任何效果。该应用程序是用 flutter 编写的。
我的函数代码:
exports.sendNotification = functions.https.onRequest((request, response) => {
const db = admin.firestore();
const fcm = admin.messaging();
db.collection("users")
.where("bananas", "==", 1666).get().then(
(result) => {
if (result.size > 0) {
result.forEach((doc) => {
const payload = {
token: doc.data().NotToken,
notification: {
title: "iam a notification",
body: "Yay",
icon: "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/231/among-us-player-white-512.png",
},
};
fcm.send(payload).then((response) => {
// Response is a message ID string.
console.log("Successfully sent message: "+
doc.data().NotToken+ " ", response);
return {success: true};
}).catch((error) => {
return {error: error.code};
});
});
}
});
response.send("Notification sent !");
functions.logger.info("Notification sent!");
return null;
});
云日志
有什么想法吗?
您是否注意到您的代码从未记录此消息?
Successfully sent message
那是因为从 Firestore 加载和通过 Cloud Messaging 发送消息都是异步调用。因此,您的 response.send("Notification sent !")
在从数据库中检索数据之前运行,此时 Cloud Functions 会终止您的代码,以防止在您说完后收费。
如果您的代码中有异步操作,您需要 return 来自代码顶层的承诺,即 resolves/rejects 当所有异步代码完成时。因此,在您的情况下,这意味着只有在您从 Firestore 加载数据并发送消息后,promise 才应该解析。
让我们从一个简单的例子开始。假设您只想发送一条消息,无论数据库中有多少文档。
exports.sendNotification = functions.https.onRequest((request, response) => {
const db = admin.firestore();
const fcm = admin.messaging();
return db.collection("users") // Add return here
.where("bananas", "==", 1666).get().then((result) => {
if (result.size > 0) {
const doc = result.docs[0]; // Get the first result
const payload = {
token: doc.data().NotToken,
notification: {
title: "iam a notification",
body: "Yay",
icon: "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/231/among-us-player-white-512.png",
},
};
return fcm.send(payload).then((response) => { // Add return here
console.log("Successfully sent message: "+
doc.data().NotToken+ " ", response);
response.send("Notification sent !"); // Move this call here
return {success: true};
}).catch((error) => {
// TODO: Send an error back to the caller
return {error: error.code};
});
}
});
});
所以顶级代码现在 return 是从 Firestore 加载数据的结果,在那里,我们 return 调用 FCM,然后又 returns return {success: true};
。当 returning 承诺时,结果会冒泡 - 因此您通常可以只保留 returning 嵌套结果。
您也不会认为我们已将 response.send
移动到调用 FCM 后运行的代码中,因为我们不想在 FCM 调用完成之前将结果发送回调用方.
以上是简单的变体,因为在现实中你有多个文档,而且只有在所有文档都完成后你才完成。
为此,我们将使用 Promise.all()
,它接受一系列承诺,并在所有这些承诺都解决后解决。因此,我们将捕获对 FCM 的所有调用(return 是一个承诺)并将它们收集在一个数组中,然后我们将其传递给 Promise.all()
.
exports.sendNotification = functions.https.onRequest((request, response) => {
const db = admin.firestore();
const fcm = admin.messaging();
return db.collection("users")
.where("bananas", "==", 1666).get().then((result) => {
if (result.size > 0) {
let promises = [];
result.forEach((doc) => {
const payload = {
token: doc.data().NotToken,
notification: {
title: "iam a notification",
body: "Yay",
icon: "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/231/among-us-player-white-512.png",
},
};
promises.push(fcm.send(payload))
});
return Promise.al(promises).then((results) => {
console.log("Successfully sent messages");
response.send("Notification sent !");
return {success: true};
});
}
});
});
虽然一次要理解很多东西,但处理异步行为在 terminating functions, in this video series on Learn JavaScript Promises with Cloud Functions 上的 Firebase 文档和相当多的教程中有很好的介绍 - 所以我建议花一些时间关于那些掌握异步代码的人。