我正在编写一个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 :(得分:0)
使您的代码混淆的部分原因是else
语句的使用。如果返回错误,则不需要else语句,并为每次回调保存4行缩进。这本身就会使事情更具可读性。
使用async:
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();
});
});