Firebase数据库onWrite的云功能触发两次

时间:2017-03-31 02:33:00

标签: node.js firebase firebase-realtime-database firebase-cloud-messaging firebase-admin

您好我正在开发通知系统,但我在删除已处理的通知数据时遇到问题。 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);
    });
});

})

2 个答案:

答案 0 :(得分:6)

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

您需要想出一种方法来检测第二次写入是为了响应数据的删除。此外,您目前在功能方面做了太多工作。没有必要在'/notification/message/{recipientUid}/{senderUid}'读取数据库的值 - 如果传递给函数,它已经交付给您。一定要read the docs about database triggers。您可以通过检查事件数据来知道该函数是否第二次被触发,如果它是null,则可以提前返回,这意味着它已被删除。

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

您可能希望查看一些显示数据库触发器的sample code

答案 1 :(得分:2)

如果有人对此仍然感到困惑,截至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}

干杯。