簡體   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