/ / Проследяване, когато в node.js са завършени няколко обратни повиквания с Mongoose и FeedParser - node.js, mongodb, асинхронен, мангуст, feedparser

Проследяване, когато в node.js са завършени няколко обратни повиквания с Mongoose и FeedParser - node.js, mongodb, асинхронен, мангуст, feedparser

Пиша пакетна процедура, за да прочета 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));