У меня есть функция, которая выполняет серию асинхронных действий, которые, в свою очередь, выполняют циклы других асинхронных действий. Я хочу знать, когда все будет готово. Казалось, что это прекрасное время, чтобы сосредоточиться на обещаниях.
Мой код в состоянии до-обещания сводится к примерно следующему (надеюсь, в процессе упрощения я не сделал этот пример бесполезным):
myClass.prototype.doMaintenance = function() {
var types = ['choreType1', 'choreType2'];
types.forEach(function(choreType) {
// find all chores of the type with score 0 (need to be done)
redisClient.zrangebyscore('chores:'+choreType, 0, 0, function(err, chores) {
if (!err) {
chores.foreach(function(chore) {
doChore(chore, function(err, result){
// chore complete!
});
})
}
});
});
}
Я прохожу цикл, и для каждого элемента в цикле я выполняю асинхронный вызов базы данных и просматриваю возвращенные результаты, выполняя еще один асинхронный вызов для каждого результата. Использование обратных вызовов для передачи уведомления о том, что все дела выполнены, кажется, в лучшем случае уродливым. Поэтому моя цель: создать обещание, которое разрешится, когда все дела будут выполнены.
Я столкнулся с двумя трудностями. Один из них - просто получить правильный синтаксис обещания. Я покажу вам, что я пробовал, ниже. Во-первых, проблема, которая может сделать это неразрешимым: предположим, что первый запрос к базе данных возвращается с единственной рутинной работой. Я (как-то) выразил это как часть общего обещания «все дела выполнены». Теперь я возвращаюсь, чтобы получить список следующего вида работы. Что, если к тому времени первая работа будет завершена? Обещание выполнить все работы по дому будет выполнено и будет выполнено до того, как будут добавлены остальные обязанности.
Я использую Q
библиотеку в node.js
среде. Я использую Redis
, но это может быть любой асинхронный источник данных.
myClass.prototype.doMaintenance = function() {
var types = ['choreType1', 'choreType2'];
var typePromises = [];
types.forEach(function(choreType) {
// find all chores of the type with score 0 (need to be done)
Q.npost(redisClient, 'zrangebyscore', ['chores:'+choreType, 0, 0]).done(chores) {
var chorePromises = [];
chores.foreach(function(chore) {
chorePromises.push(doChore(chore)); // doChore returns a promise
});
typePromises.push(Q.all(chorePromises));
});
});
return Q.all(typePromises); // at this point, typePromises is empty. Bummer!
}
То, что я пытался построить (пока еще не совсем), - это обещание, представляющее собой набор typePromises, которые, в свою очередь, являются коллекциями chorePromises.
Я думаю, что мне нужна структура, которая гласит: «Я обещаю предоставить вам обещание выполнить все работы, как только оно будет доступно». У меня начинает взорваться голова. Будем очень признательны за любые рекомендации (включая использование полностью другого шаблона).
doMaintenance
, чтобы убедиться, что цикл завершен до того, как будут выполнены все обещания. Я использую его для асинхронной загрузки ресурсов в систему, и у меня он отлично работает. - person Kiruse   schedule 11.12.2013