2015-02-09 81 views
0

我正在编写一个NodeJS脚本,它将通过Heroku的调度程序每小时运行一次。我在咀嚼我拥有的Mongo实例(mongohq/compose),然后用这些结果做一些事情。我正在使用Mongoose.js和find()命令。这将返回一组结果。有了这些结果,我需要执行额外的查询以及一些额外的异步处理(发送电子邮件等)。猫鼬查找结果和异步

长话短说,由于节点的异步性质,我需要等到所有处理完成后再致电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 2015-02-09 16:25:20

+0

或多或少只是帮助理解问题。回调地狱正在导致我过度渴望/不明白如何解决它。 – 2015-02-09 17:21:53

回答

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()。 :) – 2015-02-09 18:21:55

+0

@ DMcCarthy承诺。 https://github.com/kriskowal/q#combination – Tony 2015-02-09 20:33:05

+0

@Tony - 这就是我倾向于,但不能肯定如果这会为我做。 – 2015-02-09 20:43:54