Cloud Functions for Firebase database onWrite triggered twice

牧云@^-^@ 提交于 2019-12-22 08:35:13

问题


Hi I am developing a notification system, but I am having trouble deleting the processed notification data. The onWrite event listener is triggered twice resulting to two notifications.

Can you help me find a work around so that onWrite event listener should not be triggered twice? It is important to delete the processed data.

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);
    });
});

})

回答1:


This is a common mistake. You are writing back into the same database location (by removing the data) that was matched when the function first triggered. This means that removal will be triggering the function again to handle that second change. This is currently the expected behavior.

You will need to come up with a way to detect that the second write happened in response to the removal of data. Also, you are currently doing too much work in your function. There's no need to read the value of the database at '/notification/message/{recipientUid}/{senderUid}' - it is already being delivered to you in the event that's passed to the function. Be sure to read the docs about database triggers. You can know if the function was triggered a second time by examining the event data and returning early if it's null, which means it was removed.

Also, you don't need Promise.all() if you are dealing with a single promise. Just use then() on that single promise to continue processing, or return that single promise from then().

You might want to look at some of the sample code that shows database triggers.




回答2:


In case someone is still confused about this, as of firebase-functions v0.5.9 ; you can use onCreate(), onUpdate() or onDelete(). Just make sure your firebase-functions version is updated which you can do so by going in your functions directory and run

npm install --save firebase-functions 

Also, it has been addressed in firebase documentation and sample as well that if you are using onWrite(), as Doug has explained above, the function will be triggered for all events at that node, i.e, write; update or delete. So you should check to make sure your function doesn't get stuck in a loop. Something like:

   //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}

Cheers.



来源:https://stackoverflow.com/questions/43131416/cloud-functions-for-firebase-database-onwrite-triggered-twice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!