2015-02-09 4 views
0

Я пишу сценарий NodeJS, который будет запускаться каждый час через планировщик Heroku. Я обращаюсь к монгольскому экземпляру, который у меня есть (mongohq/compose), а затем делаю что-то с этими результатами. Я работаю с Mongoose.js и командой find(). Это возвращает массив результатов. С этими результатами мне нужно выполнить дополнительные запросы, а также некоторую дополнительную асинхронную обработку (отправка электронной почты и т. Д.).Результаты поиска Mongoose и Async

Короче говоря, из-за асинхронного характера узла мне нужно дождаться завершения всей обработки до того, как я позвоню process.exit(). Если я не выполняю сценарий раньше, и весь результирующий набор не обрабатывается.

Проблема в том, что у меня есть эффект рождественской елки вызовов в этот момент (5 вложенных вызовов asnyc).

Как правило, я бы решил это с помощью библиотеки async.js, но у меня возникла проблема, связанная с этим множеством обратных вызовов.

Как я могу убедиться, что весь этот процесс завершен до выхода из сценария?

Вот код, который я работаю с (примечание: также используя lodash ниже как _):

Topic.find({ nextNotificationDate: {$lte: moment().utc()}}, function (err, topics) { 
    if (err) { 
     console.error(err); 
     finish(); 
    } else { 

     _.forEach(topics, function (topic, callback) { 

      User.findById(topic.user, function (err, user) { 
       if (err) { 
        // TODO: impl logging 
        console.error(err); 
       } else { 

        // Create a new moment object (not moment.js, an actual moment mongoose obj) 
        var m = new Moment({ name: moment().format("MMM Do YY"), topic: topic}); 
        m.save(function(err) { 
         if(err) { 
          // TODO: impl logging 
          console.error(err); 
         } else { 

          // Send an email via postmark 
          sendReminderTo(topic, user, m._id); 

          // Update the topic with next notification times. 
          // .. update some topic fields/etc 
          topic.save(function (err) { 
           if(err) { 
            console.error(err); 
           } else { 
            console.log("Topic updated."); 
           } 
          }) 
         } 
        }) 
       } 
      }); 
      console.log("User: " + topic.user); 
     }); 
    } 
}); 
+0

Как "Елка эффект вызовов" (он же [вызов ад] (http://google.com/search?q=callback+hell)), что делает процесс» не закончить до выхода "? Или это две отдельные проблемы? – laggingreflex

+0

Более или менее просто понять проблему. Адвокат обратного звонка заставляет меня переубедить/не понять, как его решить. –

ответ

0

Часть того, что делает ваш код запутанным является использование else заявлений. Если вы вернете свои ошибки, вам не понадобится инструкция else и сохраните 4 строки отступа для каждого обратного вызова. Это само по себе сделает вещи более читабельными.

Использование асинхронной:

Topic.find({nextNotificationDate: {$lte: moment().utc()}}, function (err, topics) { 
    if (err) { 
     console.error(err); 
     return finish(err); 
    } 

    async.each(topics, function(topic, topicCallback) { 

     async.auto({ 

      user: function (callback) { 

       User.findById(topic.user, callback); 
      }, 

      moment: function(callback) { 

       var m = new Moment({name: moment().format("MMM Do YY"), topic: topic}); 
       m.save(callback); 
      }, 

      topic: ["moment", "user", function (callback, results) { 

       var m = results.moment; 
       var user = results.user; 

       sendReminderTo(topic, user, m._id); 
       topic.save(callback); 
      }] 

     }, function(err) { 
      if (err) { 
       return topicCallback(err); 
      } 

      console.log("Topic updated.") 
      return topicCallback(); 
     }); 
    }, function(err) { 
     if (err) { 
      console.error(err); 
      return finish(err); 
     } 

     return finish(); 
    }); 
}); 
+0

Ницца. Спасибо. Тем не менее, конечный результат, за которым я следую, заключается в том, как выполнить все, а затем, когда это будет сделано, знать, когда вызывать process.exit(). :) –

+0

@DMcCarthy Promises. https://github.com/kriskowal/q#combination – Tony

+0

@Tony - Это то, к чему я склонялся, но не был уверен, что это сделает это для меня. –

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