使用 Mongoose FindOne 和 Bluebird Promises 在循环中构建数组
Building an array in a loop using Mongoose FindOne & Bluebird Promises
我正在使用 Node、Mongoose 和 Bluebird,并且正在一个提供多个 RSS 提要的网站上工作。
检索提要时,我想从 table 中提取我已经保存到我的 table 中的任何文章,并将它们与提要中的任何新文章合并到 array.I 似乎无法在 returning 我的数组之前找到一种方法来等待承诺全部解决。基本问题是,当 loadRSSFeed
被调用时,它基本上立即调用 return articleList
line.How 我是否将所有这些都排成一行,所以什么都没有 returned 直到我的承诺都兑现了吗?
第一个函数只是包装了所有内容:
function loadRSSFeed(rss, newsSource) {
var articleList = [];
// Promise.each(rss.channel[0].item, function (article) {
rss.channel[0].item.forEach(function (article) {
var item = {};
item.link = tryEval(article, "article.link[0]");
Promise(function() {
return getArticle(newsSource, article, item, articleList)
.then(function() {
return articleList;
})
})
})
};
getArticle 函数如下所示:
function getArticle(newsSource, article, item, articleList) {
return Articles.findOne({ link: article.link }, function (err, doc) {
if (doc) {
articleList.push(doc._doc);
}
else {
item.title = tryEval(article, "article.title[0]");
item.pubDate = tryEval(article, "article.pubDate[0]");
item.sourceId = newsSource.id;
item.sourceName = newsSource.name;
if (item.pubDate) {
try {
item.pubDate = new Date(item.pubDate);
}
catch (err) {
item.pubDate = "";
}
};
item.contentSnippet = tryEval(article, "article.description[0]");
if (item.contentSnippet.indexOf("<") > 0) {
item.contentSnippet = item.contentSnippet.substring(0, item.contentSnippet.indexOf("<") - 1);
};
item.image = tryEval(article, "article['media:content'][0].$.url|article.thumbnail[0]");
if (!item.image) {
item.image = photoHunt(item);
if (item.image) {
item.contentSnippet = "";
}
};
if (item.title && item.link && (item.image || item.contentSnippet)) {
articleList.push(saveArticle(item));
}
}
})
}
saveArticle 函数如下所示:
function saveArticle(article) {
var curArticle = {};
if (article._id) {
curArticle = article;
curArticle._id = article._id;
curArticle.isNew = false;
}
else {
curArticle = new Articles();
curArticle.title = article.title;
curArticle.link = article.link;
curArticle.pubDate = article.pubDate;
curArticle.image = article.image;
curArticle.contentSnippet = article.contentSnippet;
curArticle.sourceName = article.name;
curArticle.sourceId = article.sourceId;
if (article.haters) {
curArticle.haters = article.haters;
};
if (article.lovers) {
curArticle.lovers = article.lovers;
};
if (article.readers) {
curArticle.readers = article.readers;
};
}
curArticle.save(function (err) {
if (err)
console.log(err);
});
return curArticle;
};
这是 Articles 模型的样子,以防出现问题:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
// NewsSchema = new Schema({ name: String });
var ArticlesSchema = new Schema({
title: String,
link: String,
pubDate: Date,
image: String,
contentSnippet: String,
sourceName: String,
lovers: [],
haters: [],
readers: [],
forumLinks: []
});
module.exports = mongoose.model('Articles', ArticlesSchema);
在我看来,您可以只使用 Bluebird 的 Promise.map()
来遍历所有 RSS 提要并等待它们全部完成:
function loadRSSFeed(rss, newsSource) {
// Promise.each(rss.channel[0].item, function (article) {
return Promise.map(rss.channel[0].item, function(article) {
var item = {};
item.link = tryEval(article, "article.link[0]");
return getArticle(newsSource, article, item, articleList);
}).then(function(articleList) {
// filter out any empty items
return articleList.filter(function(article) {
return !!article;
});
});
}
function getArticle(newsSource, article, item) {
var find = Promise.promisify(Articles.findOne, {context: Articles});
return find({link: article.link}).then(doc) {
if (doc) {
return doc._doc;
} else {
item.title = tryEval(article, "article.title[0]");
item.pubDate = tryEval(article, "article.pubDate[0]");
item.sourceId = newsSource.id;
item.sourceName = newsSource.name;
if (item.pubDate) {
try {
item.pubDate = new Date(item.pubDate);
} catch (err) {
item.pubDate = "";
}
};
item.contentSnippet = tryEval(article, "article.description[0]");
if (item.contentSnippet.indexOf("<") > 0) {
item.contentSnippet = item.contentSnippet.substring(0, item.contentSnippet.indexOf("<") - 1);
};
item.image = tryEval(article, "article['media:content'][0].$.url|article.thumbnail[0]");
if (!item.image) {
item.image = photoHunt(item);
if (item.image) {
item.contentSnippet = "";
}
};
if (item.title && item.link && (item.image || item.contentSnippet)) {
return saveArticle(item);
}
}
// unsure what your code intends if there was no article here
// this will return undefined which will get filtered out later
})
}
function saveArticle(article) {
return new Promise(function(resolve, reject) {
var curArticle;
if (article._id) {
curArticle = article;
curArticle._id = article._id; // don't know why this is needed since curArticle === article already
curArticle.isNew = false;
} else {
curArticle = new Articles();
curArticle.title = article.title;
curArticle.link = article.link;
curArticle.pubDate = article.pubDate;
curArticle.image = article.image;
curArticle.contentSnippet = article.contentSnippet;
curArticle.sourceName = article.name;
curArticle.sourceId = article.sourceId;
if (article.haters) {
curArticle.haters = article.haters;
};
if (article.lovers) {
curArticle.lovers = article.lovers;
};
if (article.readers) {
curArticle.readers = article.readers;
};
}
curArticle.save(function (err) {
if (err) reject(err) else resolve(curArticle);
});
});
};
我正在使用 Node、Mongoose 和 Bluebird,并且正在一个提供多个 RSS 提要的网站上工作。
检索提要时,我想从 table 中提取我已经保存到我的 table 中的任何文章,并将它们与提要中的任何新文章合并到 array.I 似乎无法在 returning 我的数组之前找到一种方法来等待承诺全部解决。基本问题是,当 loadRSSFeed
被调用时,它基本上立即调用 return articleList
line.How 我是否将所有这些都排成一行,所以什么都没有 returned 直到我的承诺都兑现了吗?
第一个函数只是包装了所有内容:
function loadRSSFeed(rss, newsSource) {
var articleList = [];
// Promise.each(rss.channel[0].item, function (article) {
rss.channel[0].item.forEach(function (article) {
var item = {};
item.link = tryEval(article, "article.link[0]");
Promise(function() {
return getArticle(newsSource, article, item, articleList)
.then(function() {
return articleList;
})
})
})
};
getArticle 函数如下所示:
function getArticle(newsSource, article, item, articleList) {
return Articles.findOne({ link: article.link }, function (err, doc) {
if (doc) {
articleList.push(doc._doc);
}
else {
item.title = tryEval(article, "article.title[0]");
item.pubDate = tryEval(article, "article.pubDate[0]");
item.sourceId = newsSource.id;
item.sourceName = newsSource.name;
if (item.pubDate) {
try {
item.pubDate = new Date(item.pubDate);
}
catch (err) {
item.pubDate = "";
}
};
item.contentSnippet = tryEval(article, "article.description[0]");
if (item.contentSnippet.indexOf("<") > 0) {
item.contentSnippet = item.contentSnippet.substring(0, item.contentSnippet.indexOf("<") - 1);
};
item.image = tryEval(article, "article['media:content'][0].$.url|article.thumbnail[0]");
if (!item.image) {
item.image = photoHunt(item);
if (item.image) {
item.contentSnippet = "";
}
};
if (item.title && item.link && (item.image || item.contentSnippet)) {
articleList.push(saveArticle(item));
}
}
})
}
saveArticle 函数如下所示:
function saveArticle(article) {
var curArticle = {};
if (article._id) {
curArticle = article;
curArticle._id = article._id;
curArticle.isNew = false;
}
else {
curArticle = new Articles();
curArticle.title = article.title;
curArticle.link = article.link;
curArticle.pubDate = article.pubDate;
curArticle.image = article.image;
curArticle.contentSnippet = article.contentSnippet;
curArticle.sourceName = article.name;
curArticle.sourceId = article.sourceId;
if (article.haters) {
curArticle.haters = article.haters;
};
if (article.lovers) {
curArticle.lovers = article.lovers;
};
if (article.readers) {
curArticle.readers = article.readers;
};
}
curArticle.save(function (err) {
if (err)
console.log(err);
});
return curArticle;
};
这是 Articles 模型的样子,以防出现问题:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
// NewsSchema = new Schema({ name: String });
var ArticlesSchema = new Schema({
title: String,
link: String,
pubDate: Date,
image: String,
contentSnippet: String,
sourceName: String,
lovers: [],
haters: [],
readers: [],
forumLinks: []
});
module.exports = mongoose.model('Articles', ArticlesSchema);
在我看来,您可以只使用 Bluebird 的 Promise.map()
来遍历所有 RSS 提要并等待它们全部完成:
function loadRSSFeed(rss, newsSource) {
// Promise.each(rss.channel[0].item, function (article) {
return Promise.map(rss.channel[0].item, function(article) {
var item = {};
item.link = tryEval(article, "article.link[0]");
return getArticle(newsSource, article, item, articleList);
}).then(function(articleList) {
// filter out any empty items
return articleList.filter(function(article) {
return !!article;
});
});
}
function getArticle(newsSource, article, item) {
var find = Promise.promisify(Articles.findOne, {context: Articles});
return find({link: article.link}).then(doc) {
if (doc) {
return doc._doc;
} else {
item.title = tryEval(article, "article.title[0]");
item.pubDate = tryEval(article, "article.pubDate[0]");
item.sourceId = newsSource.id;
item.sourceName = newsSource.name;
if (item.pubDate) {
try {
item.pubDate = new Date(item.pubDate);
} catch (err) {
item.pubDate = "";
}
};
item.contentSnippet = tryEval(article, "article.description[0]");
if (item.contentSnippet.indexOf("<") > 0) {
item.contentSnippet = item.contentSnippet.substring(0, item.contentSnippet.indexOf("<") - 1);
};
item.image = tryEval(article, "article['media:content'][0].$.url|article.thumbnail[0]");
if (!item.image) {
item.image = photoHunt(item);
if (item.image) {
item.contentSnippet = "";
}
};
if (item.title && item.link && (item.image || item.contentSnippet)) {
return saveArticle(item);
}
}
// unsure what your code intends if there was no article here
// this will return undefined which will get filtered out later
})
}
function saveArticle(article) {
return new Promise(function(resolve, reject) {
var curArticle;
if (article._id) {
curArticle = article;
curArticle._id = article._id; // don't know why this is needed since curArticle === article already
curArticle.isNew = false;
} else {
curArticle = new Articles();
curArticle.title = article.title;
curArticle.link = article.link;
curArticle.pubDate = article.pubDate;
curArticle.image = article.image;
curArticle.contentSnippet = article.contentSnippet;
curArticle.sourceName = article.name;
curArticle.sourceId = article.sourceId;
if (article.haters) {
curArticle.haters = article.haters;
};
if (article.lovers) {
curArticle.lovers = article.lovers;
};
if (article.readers) {
curArticle.readers = article.readers;
};
}
curArticle.save(function (err) {
if (err) reject(err) else resolve(curArticle);
});
});
};