Пиша пакетна процедура, за да прочета RSS емисия,и съхранявайте съдържанието в 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();
Отговори:
1 за отговор № 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));