我正在编写批处理来读取RSS源,并通过Mongoose将内容存储在MongoDB中。我会运行脚本,它会处理内容很好......但脚本不会返回到控制台。我的假设是我的数据库连接仍处于打开状态,这就是我没有返回的原因。
我无法跟踪解析完成的时间,因为我仍然可能会进行一些mongoose保存操作。
所以,我写了一个函数来跟踪我的开放数据库连接,以及我的RSS解析的状态。但是我的代码最终变得非常冗长。我想知道是否有更好的模型/模式来做这样的事情。
var FeedParser = require('feedparser')
, mongoose = require('mongoose');
var TEST_RSS_URL = "./test/data/20120303-seattle.rss";
var OPEN_DB_CONNECTIONS = 0;
var PARSING_DONE = false;
/*
* Keeps track of open database connections, and closes the connection when done
*/
function track_and_close_database(mode) {
switch(mode)
{
case 'open':
OPEN_DB_CONNECTIONS++;
break;
case 'close':
OPEN_DB_CONNECTIONS--;
if (0 == OPEN_DB_CONNECTIONS && PARSING_DONE) conn.close();
break;
case 'parseStart':
PARSING_DONE = false;
break;
case 'parseEnd':
PARSING_DONE = true;
if (0 == OPEN_DB_CONNECTIONS && PARSING_DONE) conn.close();
break;
}
}
function parse_stuff(stuff) {
// do some stuff
setTimeout(console.log("parsed some stuff",20));
}
function main() {
parser = new FeedParser();
parser.on('article', function(article) {
track_and_close_database('open');
// check to see if we already have this listing
stuff_model = conn.model('stuff');
stuff = stuff_model.findOne({'href': article.link}, function (error, doc) {
if (error) {
track_and_close_database('close');
return;
}
// this one doesn't exist yet, parse and save
if (null == doc) {
listing = parse_stuff(article);
// if listing is valid, save it!
if (null != listing) {
listing.save(function (error) { track_and_close_database('close') });
}
// parsing failed
else track_and_close_database('close');
}
// nothing to do, already in the database
else track_and_close_database('close');
});
});
// Completed parsing the RSS file
parser.on('end', function(article) {
track_and_close_database('parseEnd');
});
track_and_close_database('parseStart')
parser.parseFile(TEST_RSS_URL);
}
// run this thing
main();
答案 0 :(得分:1)
我也遇到过这个问题。我认为处理这个问题的首选方法是使用事件,但是在查看源代码时,似乎没有任何内容可以保留某些类型的操作。我最终把它挂到了EventEmitter上。更好的是,如果Mongoose在保存之前和之后发出事件,那么我就不必将其插入到我的所有模型中。
以下是我如何做到这一点的示例:
/* lib/render_log.js */
/* Model for managing RenderLog */
var common = require("./common");
common.initialize_locals(global);
var mongoose = require("mongoose"),
Schema = mongoose.Schema;
var RenderLogSchema = new Schema({
renderer: String,
template: String,
content: {}
});
RenderLogSchema.pre('save', function(next){
this.db.model('RenderLog').emit('open_db_op', this);
next();
});
RenderLogSchema.post('save', function(){
this.db.model('RenderLog').emit('close_db_op', this);
});
mongoose.connect('mongodb://localhost/time-jr-development');
var RenderLog = mongoose.model("RenderLog", RenderLogSchema);
exports = module.exports = RenderLog;
接下来是我的测试可执行文件:
/* bin/test_mongoose.js */
var async = require('async');
var RenderLog = require("../lib/render_log");
var ConnectionManager = {
open_db_ops: 0,
new_db_op: function(){
this.open_db_ops ++;
},
close_db_op: function(){
this.open_db_ops --;
},
close: function(self){
if(!self)
self = this;
if(self.open_db_ops > 0){
console.log("Waiting...")
process.nextTick(async.apply(self.close, self));
}else{
RenderLog.db.close();
}
}
};
RenderLog.on("open_db_op", function(model){
ConnectionManager.new_db_op();
});
RenderLog.on("close_db_op", function(model){
ConnectionManager.close_db_op();
})
new RenderLog({renderer: "foo", template: "foo.html", content: {"bar": 1}}).save();
new RenderLog({renderer: "foo", template: "foo.html", content: {"bar": 2}}).save();
new RenderLog({renderer: "foo", template: "foo.html", content: {"bar": 3}}).save();
new RenderLog({renderer: "foo", template: "foo.html", content: {"bar": 4}}).save();
new RenderLog({renderer: "foo", template: "foo.html", content: {"bar": 5}}).save();
// You have to push this to the next tick otherwise it gets called before the save
// events have been emitted
async.nextTick(async.apply(ConnectionManager.close, ConnectionManager));