[英]How to mix sync and async code in javascript in node.js and MongoDb
我有这段代码:
var re = new RegExp("<a href=\"(news[^?|\"]+).*?>([^<]+)</a>", "g");
var match;
while (match = re.exec(body)){
var href = match[1];
var title = match[2];
console.log(href);
db.news.findOne({ title: title }, function(err, result){
if (err) {
console.log(err);
} else {
console.log(href);
// more codes here
}
});
}
以下是示例输出:
news/2015/02/20/347332.html
news/2015/02/19/347307.html
news/2015/02/19/347176.html
news/2015/02/19/347176.html
news/2015/02/19/347176.html
news/2015/02/19/347176.html
所以,我有三组数据要传递给findOne函数。 但是,只有最后一个传递了三次。 如何解决?
更新基于jfriend00和Neta Meta,这是使它工作的两种方法:
var re = new RegExp("<a href=\"(news[^?|\"]+).*?>([^<]+)</a>", "g");
var cnt = 0;
function next(){
var match = re.exec(body);
if (match) {
var href = match[1];
var title = match[2];
db.news.findOne({ title: title }, function(err, result){
if (err) {
console.log(err);
} else {
console.log(href);
// more codes here
}
});
}
}
next();
要么
var asyncFunction = function(db, href, title){
db.news.findOne({ title: title }, function(err, result){
if (err) {
console.log(err);
} else {
console.log(href);
// more codes here
}
});
}
var re = new RegExp("<a href=\"(news[^?|\"]+).*?>([^<]+)</a>", "g");
var match;
var cnt = 0;
while (match = re.exec(body)) {
asyncFunction(db, match[1], match[2]);
}
您没有得到预期输出的原因是因为您正在共享所有数据库调用的href
和title
变量。 因此,对于每个异步数据库操作,不会单独跟踪那些。
如果您可以立即执行所有异步函数并且可以按任何顺序处理数据,那么您只需要创建一个闭包,以便为每次循环调用单独捕获局部变量:
var re = new RegExp("<a href=\"(news[^?|\"]+).*?>([^<]+)</a>", "g");
var match, cntr = 0;
while (match = re.exec(body)){
(function(href, title, index) {
console.log(href);
db.news.findOne({ title: title }, function(err, result){
if (err) {
console.log(err);
} else {
console.log(href);
// more codes here
}
});
})(match[1], match[2], cntr++);
}
如果你想连续发出请求(一次只发一个),那么你就不能真正使用while
循环来控制事情,因为它会立即启动它们。 我倾向于使用这种类型的设计模式与next()
本地函数而不是while
循环进行串行操作:
function someFunction() {
var re = new RegExp("<a href=\"(news[^?|\"]+).*?>([^<]+)</a>", "g");
function next() {
var match = re.exec(body);
if (match) {
var href = match[1];
var title = match[2];
db.news.findOne({ title: title }, function(err, result){
if (err) {
console.log(err);
} else {
console.log(href);
// more codes here
// launch the next iteration
next();
}
});
}
}
// run the first iteration
next();
}
使用的承诺,你可以promisify()
的db.news.findOne()
函数,以便它返回一个承诺,收集所有的比赛到一个数组,然后使用.reduce()
进行排序的所有数据库与承诺的要求.then()
提供测序的方法。
你只得到最后一个href的原因是因为迭代并调用fineOne这是一个asyc操作。 虽然不会等到findOne完成它只是在findOne完成时继续运行,同时到达循环结束,这就是为什么你得到相同的href。
有几种方法你可以做到这一点,1承诺(我认为优先) - 你必须阅读有关承诺以了解更多。 但结帐: https : //github.com/petkaantonov/bluebird http://www.html5rocks.com/en/tutorials/es6/promises/和http://promise-nuggets.github.io/articles/03-power -of-然后同步-processing.html
将异步函数包装在另一个函数中并绑定任何你想要的东西(不是一个好的选择,但可能)
// wrapping your async function.
var asyncFunction = function(title,href, successCb, failCb){
db.news.findOne({ title: title }, function(err, result){
if (err) {
failCb();
} else {
successCb()
}
});
};
var re = new RegExp("<a href=\"(news[^?|\"]+).*?>([^<]+)</a>", "g");
var match;
while (match = re.exec(body)){
var href = match[1];
var title = match[2];
asyncFunction.call(this,title, href, function success(){}, function fail(){} );
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.