lowe0292 lowe0292 - 1 year ago 59
Node.js Question

Why are my firebase callbacks being triggered multiple times?

I've got a small node server listening for changes in firebase and sending emails on certain conditions. Here's the code:

var Firebase = require('firebase');
var ref = new Firebase(process.env.FIREBASE_URL);
ref.authWithCustomToken(process.env.FIREBASE_SECRET, function (err) {
if (err) {
console.log(new Date().toString(), 'Firebase Authentication Failed!', err);
EmailService.send('Firebase authentication failed', 'errors@domain.com', err);
} else {
ref.child('applicants').on('child_added', function (snapshot) {
var applicant = snapshot.val();
if (!(applicant.alerts && applicant.alerts.apply)) {
console.log(new Date().toString(), 'New Applicant: ', applicant);
var body = applicant.firstName + ' ' + applicant.lastName + '\n' + applicant.email + '\n' + applicant.phoneNumber;
.send('New Applicant', 'applicants@entercastle.com', body)
.then(function () {
.catch(function (err) { console.log(new Date().toString(), err); });

However, I keep getting duplicate emails. The weirdest part is, the logs only show a single "New Applicant : ..." statement for each applicant, despite multiple emails being sent.

Any ideas what's causing this or how to fix it?


Answer Source

Your child_added events will be triggered each time authWithCustomToken() succeeds. Each time the page is reloaded or reauthenticated, new listeners are attached, and each user will trigger a new child_added event, and the emails will be resent.

The child_added event is typically used when retrieving a list of items in Firebase. Unlike value which returns the entire contents of the location, child_added is triggered once for each existing child and then again every time a new child is added to the specified path. The event callback is passed a snapshot containing the new child's data.

(emphasis mine)

If you only ever want to send the emails once, a better approach would be to use a queue strategy, where you "queue" an activity (e.g. welcome email) when a user is created.

Then your service can read the queue and delete the task once they successfully complete. In this way, you won't have dups.