Cloud Functions for Firebase 数据库 onWrite 触发了两次
Cloud Functions for Firebase database onWrite triggered twice
您好,我正在开发一个通知系统,但我无法删除已处理的通知数据。 onWrite
事件侦听器被触发两次,导致两个通知。
你能帮我找到一个解决方法,使 onWrite 事件侦听器不应该被触发两次吗?重要的是删除处理过的数据。
exports.sendMessageNotification = functions.database.ref('/notification/message/{recipientUid}/{senderUid}').onWrite(event => {
/* processing notification and sends FCM */
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const toRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
console.error('Failure sending notification to', tokens[index], error);
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
toRemove.push(tokensSnapshot.ref.child(tokens[index]).remove());
}
}
});
//Deletes processed notification
console.log("Removing notification");
const getNotificationPromise = admin.database().ref(`/notification/message/${recipientUid}/${senderUid}`).once('value');
return Promise.all([getNotificationPromise]).then(results => {
const notificationSnapshot = results[0];
toRemove.push(notificationSnapshot.ref.remove());
console.log("Removing tokens.")
return Promise.all(toRemove);
});
//return Promise.all(tokensToRemove);
});
});
})
这是一个常见的错误。您正在写回到函数首次触发时匹配的同一数据库位置(通过删除数据)。这意味着删除将再次触发该功能以处理第二次更改。这是目前预期的行为。
您需要想出一种方法来检测第二次写入是为了响应数据删除而发生的。另外,你目前在你的职能上做了太多的工作。无需读取 '/notification/message/{recipientUid}/{senderUid}'
处的数据库值 - 它已经在传递给函数的事件中传递给您。一定要read the docs about database triggers。您可以通过检查事件数据来了解该函数是否被第二次触发,如果它为空,则提前 returning,这意味着它已被删除。
此外,如果您处理的是单个承诺,则不需要 Promise.all()。只需在单个承诺上使用 then() 继续处理,或者 return 来自 then() 的单个承诺。
您可能想查看一些显示数据库触发器的 sample code。
如果有人对此仍然感到困惑,截至 firebase-functions v0.5.9;您可以使用 onCreate()、onUpdate() 或 onDelete()。 只需确保您的 firebase-functions 版本已更新,您可以通过进入您的函数目录和 运行
npm install --save firebase-functions
此外,它已在 firebase 文档和 sample 中得到解决,如果您正在使用 onWrite(),正如 Doug 上面所解释的那样,该函数将针对该节点上的所有事件触发,即, 写;更新或删除。所以你应该检查以确保你的函数不会陷入循环。类似于:
//if data is not new
if (event.data.previous.exists()) {return}
// Exit when the data is deleted; needed cuz after deleting the node this function runs once more.
if (!event.data.exists()) {return}
干杯。
您好,我正在开发一个通知系统,但我无法删除已处理的通知数据。 onWrite
事件侦听器被触发两次,导致两个通知。
你能帮我找到一个解决方法,使 onWrite 事件侦听器不应该被触发两次吗?重要的是删除处理过的数据。
exports.sendMessageNotification = functions.database.ref('/notification/message/{recipientUid}/{senderUid}').onWrite(event => {
/* processing notification and sends FCM */
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const toRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
console.error('Failure sending notification to', tokens[index], error);
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
toRemove.push(tokensSnapshot.ref.child(tokens[index]).remove());
}
}
});
//Deletes processed notification
console.log("Removing notification");
const getNotificationPromise = admin.database().ref(`/notification/message/${recipientUid}/${senderUid}`).once('value');
return Promise.all([getNotificationPromise]).then(results => {
const notificationSnapshot = results[0];
toRemove.push(notificationSnapshot.ref.remove());
console.log("Removing tokens.")
return Promise.all(toRemove);
});
//return Promise.all(tokensToRemove);
});
});
})
这是一个常见的错误。您正在写回到函数首次触发时匹配的同一数据库位置(通过删除数据)。这意味着删除将再次触发该功能以处理第二次更改。这是目前预期的行为。
您需要想出一种方法来检测第二次写入是为了响应数据删除而发生的。另外,你目前在你的职能上做了太多的工作。无需读取 '/notification/message/{recipientUid}/{senderUid}'
处的数据库值 - 它已经在传递给函数的事件中传递给您。一定要read the docs about database triggers。您可以通过检查事件数据来了解该函数是否被第二次触发,如果它为空,则提前 returning,这意味着它已被删除。
此外,如果您处理的是单个承诺,则不需要 Promise.all()。只需在单个承诺上使用 then() 继续处理,或者 return 来自 then() 的单个承诺。
您可能想查看一些显示数据库触发器的 sample code。
如果有人对此仍然感到困惑,截至 firebase-functions v0.5.9;您可以使用 onCreate()、onUpdate() 或 onDelete()。 只需确保您的 firebase-functions 版本已更新,您可以通过进入您的函数目录和 运行
npm install --save firebase-functions
此外,它已在 firebase 文档和 sample 中得到解决,如果您正在使用 onWrite(),正如 Doug 上面所解释的那样,该函数将针对该节点上的所有事件触发,即, 写;更新或删除。所以你应该检查以确保你的函数不会陷入循环。类似于:
//if data is not new
if (event.data.previous.exists()) {return}
// Exit when the data is deleted; needed cuz after deleting the node this function runs once more.
if (!event.data.exists()) {return}
干杯。