4

您好我正在开发一个通知系统,但我无法删除已处理的通知数据。事件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);
    });
});

})
4

2 回答 2

6

这是一个常见的错误。您正在写回函数首次触发时匹配的同一数据库位置(通过删除数据)。这意味着删除将再次触发该函数以处理第二次更改。这是当前的预期行为。

您将需要想出一种方法来检测第二次写入是为了响应数据的删除而发生的。此外,您目前在您的功能中做的工作太多。无需读取数据库的值'/notification/message/{recipientUid}/{senderUid}'- 如果传递给函数,它已经被传递给您。请务必阅读有关数据库触发器的文档。您可以通过检查事件数据并在它为空时提前返回来知道该函数是否被第二次触发,这意味着它已被删除。

此外,如果您正在处理单个承诺,则不需要 Promise.all() 。只需在该单个 Promise 上使用 then() 以继续处理,或从 then() 返回该单个 Promise。

您可能想查看一些显示数据库触发器的示例代码。

于 2017-03-31T03:38:37.957 回答
3

如果有人仍然对此感到困惑,firebase-functions v0.5.9 开始;您可以使用 onCreate()、onUpdate() 或 onDelete()。只需确保您的 firebase-functions 版本已更新,您可以通过进入您的函数目录并运行来执行此操作

npm install --save firebase-functions 

此外,Firebase 文档和示例中也已解决,如果您使用 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}

干杯。

于 2017-08-18T20:47:19.550 回答