Mongoose查找结果和异步

时间:2015-02-09 15:56:11

标签: javascript node.js asynchronous mongoose

我正在编写一个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);
        });
    }
});

1 个答案:

答案 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();
    });
});