2015-01-26 7 views
1

У меня есть небольшой сервер узлов, который слушает изменения в firebase и отправляет электронные письма на определенных условиях. Вот код:Почему мои вызовы firebase запускаются несколько раз?

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', '[email protected]', 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; 
       EmailService 
       .send('New Applicant', '[email protected]', body) 
       .then(function() {     
        ref.child('applicants').child(snapshot.key()).child('alerts').child('apply').set(true); 
       }) 
       .catch(function (err) { console.log(new Date().toString(), err); }); 
      } 
     }); 
    }                                      
}); 

Однако я продолжаю получать дубликаты писем. Самое странное, что в журналах отображается только одно заявление «Новый заявитель: ...» для каждого заявителя, несмотря на отправку нескольких электронных писем.

Любые идеи, что вызывает это или как его исправить?

Спасибо!

ответ

1

Ваши дочерние события будут запускаться каждый раз, когда authWithCustomToken() будет успешным. Каждый раз, когда страница перезагружается или повторно проверяется, подключаются новые слушатели, и каждый пользователь запускает новое событие child_added, и электронные письма будут повторно отправлены.

Событие child_added обычно используется при получении списка элементов в Firebase. В отличие от значения, которое возвращает все содержимое , child_added запускается один раз для каждого существующего дочернего , а затем снова каждый раз, когда новый ребенок добавляется к указанному пути. Обратный вызов события получает моментальный снимок, содержащий данные нового ребенка .

(курсив мой)

Если вы только когда-либо хотите, чтобы отправить электронную почту один раз, лучше было бы использовать queue strategy, где «очередь» деятельность (например, приветствуется по электронной почте), когда пользователь создано.

Затем ваша служба может прочитать очередь и удалить задачу после ее успешного завершения. Таким образом, у вас не будет дубликатов.

+0

Хм, я думал, что 'если (! (заявитель.alerts && претендент.alerts.apply)) 'будет учитывать дочерний_адбед-триггер один раз для каждого существующего дочернего элемента. Кажется, что обратный вызов auth вызван несколько раз и заставляет слушателей подключаться несколько раз, поэтому я добавил логическое имя firstLoad, которое я проверяю в обратном вызове auth, прежде чем регистрировать слушателей, но я все равно получаю дубликаты. Я, вероятно, вернусь в очередь, но мне все равно хотелось бы узнать, чего я не вижу. Любые мысли, @ Като? – lowe0292

+0

В этом вопросе недостаточно кода, чтобы помочь вам понять, почему он вызывается более одного раза, кроме того факта, что метод auth может вызываться более одного раза и что он будет вызываться для каждой записи, каждый раз, когда страница грузы. Я уверен, что какой-то вариант игры в игре, но без [mcve] (http://stackoverflow.com/help/mcve) трудно быть более конкретным. – Kato

+0

Извините @ Kato, я немного очистил код, пытаясь сделать его более mcv. Вот [gist] (https://gist.github.com/lowe0292/fa3737fdabdff4059629). Благодаря! – lowe0292

2

удаление существующего слушателя перед добавлением нового слушателя будет решить эту проблему

попробовать это off() событие, перед тем on() событие

ref.child('applicants').off(); // it will remove existing listener 

, то ваш код

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; 
     EmailService 
      .send('New Applicant', '[email protected]', body) 
      .then(function() { 
       ref.child('applicants').child(snapshot.key()).child('alerts').child('apply').set(true); 
      }) 
      .catch(function(err) { 
       console.log(new Date().toString(), err); 
      }); 
    } 
}); 
+1

Спасибо. Это исправило мою проблему. –

+1

Исправлена ​​моя тоже .. – satheeshwaran

Смежные вопросы