"Event chaining" в node.js

Проблема 1
Я знаю про прекрасный модуль async, но он не совсем подходит в данной ситуации, по крайней мере я не нашел способа лаконично его применить.
Ситуация следующая. Я пишу парсер который получает данные через стороннее апи, обрабатывает их и затем сохраняет в нужном мне виде в базе. Данные поступают через разные интерфейсы и методы апи, склеиваются вместе, скачиваются картинки по ссылкам из ответа и т.д.
Парсер наследуется от EventEmitter, и на определенных этапах своей работы, соответственно эмитирует события. Сделано это для того, чтобы можно было навешивать различные колбэки, без хардкода. Скажем если мы запрашиваем через апи список холодильников, у них будут свои характеристики, если же запрашиваем телевизоры - свои. Соответственно и обрабатывать их нужно по разному.

Вопрос 1: как правильно эмитировать события, скажем 'end' (парсер закончил работу).
Вот например я запрашиваю через апи некий список товаров. При поступлении ответа от апи, эмитируется событие 'itemlist', в списке товаров содержатся урлы с ссылками на фото товара, которые нам также необходимо скачать, после их скачивании эмитируется событие 'photos'. Как сэмитировать событие 'end', которое наступит после того как произошло 'itemlist' и 'photos'?

я сделал это так:
// <!-- эмит события end
var emitted = {itemlist:false, photos:false};
	
self.once('itemlist', function(){
	emitted.itemlist = true;
	if (emitted.photos){
		process.nextTick(self.emit.bind( self, 'end' ));
	}
});

self.once('photos', function(err, res, txt){			
	emitted.photos = true;
	if (emitted.itemlist){
		process.nextTick(self.emit.bind( self, 'end' ));
	}
});
// -->

работает, но нутро почему-то подсказывает, что это пипец какой костыль. тем более, что делать, если у нас не два эвента, а 5 например.

Проблема 2
Скажем, мы получаем список с названиями товаров через апи на разных языках, скажем на пяти, т.е. делаем 3 запроса (3 языка). При получении ответа, эмитируем событие 'list'
После получения всех списков, эмитируем событие 'lists' (получены все списки).
Здесь можно воспользоваться async.parallel
async.parallel([
    function(cb){ getLang(1, function(){self.emit('list');cb();}) },
    function(cb){ getLang(2, function(){self.emit('list');cb();}) },
    function(cb){ getLang(3, function(){self.emit('list');cb();}) },
],function(err){self.emit('lists')});

Я навешиваю несколько обработчиков на эвент 'list', которые извлекают из списка нужные данные и склеивает их с неким общим объектом (который будет в дальнейшем сохранен в базе).
Вопрос 2: Гарантирует ли такая реализация то, что при наступлении события 'lists' общий объект уже будет готов для сохранения и все обработчики события list над каждым списком уже отработают? nextTick нужен в финальном колбеке или нет?
  • Вопрос задан
  • 2677 просмотров
Пригласить эксперта
Ответы на вопрос 2
Что касается первого вопроса, я делаю так:
var await = new (require("atma-class")).Await;

self.once("itemlist", await.delegate());
self.once("photos", await.delegate());

await
    .done(function() {
        self.emit("end");
    })
    .fail(function(error) {
        self.emit("error", error);
    });
Ответ написан
Комментировать
icelaba
@icelaba
Знаю и умею всё
Возьмите любую promise библиотеку
например https://github.com/kriskowal/q
или из списка тут wiki.commonjs.org/wiki/Promises/A
тогда сведение данных с кучи источников будет выглядеть
q.all([source1, .., sourceN])
.then(function(results){
})

забыл как страшный сон про async и тп
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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