Проблема 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 нужен в финальном колбеке или нет?