繁体   English   中英

如何在node.js和MongoDb中的javascript中混合同步和异步代码

[英]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]);
}

您没有得到预期输出的原因是因为您正在共享所有数据库调用的hreftitle变量。 因此,对于每个异步数据库操作,不会单独跟踪那些。

如果您可以立即执行所有异步函数并且可以按任何顺序处理数据,那么您只需要创建一个闭包,以便为每次循环调用单独捕获局部变量:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM