Actor
@Actor

Что не так с колбеками и архитектурой?

Есть NodeJS,
Не пойму как сделать архитектуру правильную, многие действия являются асинхронными и как уследить за всем что бы не городить кучу колбэков и тесты запускать.

Допустим имеется класс-наблюдающий за чем-либо, этот класс выполняет функцию получения данных и передачу в нужное действие классом обработчиком, класс-обработчик выполняет какие-либо проверки и делает запись в БД. Вся эта связка усложняется асинхронными запросами.
Проблема в том, что иногда требуется определенная последовательность, да можно использовать async от Node. Но это не решение, проблема явно в архитектуре.
P.S. Да я знаю, что для работы с БД нужен дополнительный слой, но в данном примере вопрос не об этом и думаю можно обойтись без него.

class Watcher{
   get EventEmitter() { return this._eventEmitter; }
  constructor(){
     
  }
  DataReceived(data){
      ...
      this._eventEmitter.emit('dataReceived',data);
 }
}
class Worker{
  get Watcher() { return this._watcher; }
  get Database() { return this._database; }
  constructor(){
    this._database = orm.connect(....);
    this._watcher = new Watcher();
    this._watcher.EventEmitter.on('dataReceived', function(data) {
      this.ProcessReceivedData(data);  
  }
  ProcessReceivedData(data) {
     var self = this;
     this._database.models.A.find(... , function(err,data){
       if (data.length > 1) {
         self._database.models.B.create({...}, function(err,data) { });
       }else{
         self._database.models.B.update({...}, function(err,data) { });
       }
     }  
  }
}

тест
it('Should create record in DB', function (done) {
  var Wkr = new Worker();
  Wkr.Watcher.DataReceived("something");  //инсценируем отправку данных
  //Проверяем есть ли запись, но она с вероятностью 99% не успеет создаться
  //поскольку обращение к базе не дожидается ответа
  Wkr.Database.models.Device.get(1, function (e, d) {
                    should.exist(d);
                    done();
                });
            });
        });

И как теперь протестировать что создалась ли запись и/или обновилась?
Да можно создать событие и эмитеть типа того, что ниже. Но мы получим дублирование когда.
self._database.models.B.create({...}, function(err,data) { self.emitter.emit('onProcessedData') });
...
self._database.models.B.update({...}, function(err,data) { self.emitter.emit('onProcessedData') });


Вобщем что то я запутался...
  • Вопрос задан
  • 215 просмотров
Пригласить эксперта
Ответы на вопрос 1
Событийная модель + промисы обычно предоставляют всё необходимое для структурирования асинхронного кода. У вас же проблема в применении. Такие действия как create/update, например, должны генерировать свои собственные события в колбеке, на которые уже потом будет подписан общий код (и по хорошему там должна быть функция onProcessedData, которая уже внутри себя генерирует соответствующее событие, а не вложенный эмит):

create({}, function() {
  object.emit("create");
  // В триггеры подобных событий, к тому же, лучше передавать
  // дополнительные аргументы, чтобы можно было отличить,
  // что именно создано когда это потребуется
});

update({}, function() {
  object.emit("update");
});

object.on("create update", onProcessedData);


Помимо этого не будет лишним хоть иногда использовать вертикальные отступы и почаще пробелы. И конструктор, для наглядности, стоит описывать в начале объявления класса.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы