一尘不染

在Node.js中进行同步MongoDB查询的正确方法是什么?

node.js

我正在为MongoDB使用Node.JS驱动程序,我想执行一个同步查询,例如:

function getAThing()
{
    var db = new mongo.Db("mydatabase", server, {});

    db.open(function(err, db)
    {
        db.authenticate("myuser", "mypassword", function(err, success)
        {
            if (success)
            {
                db.collection("Things", function(err, collection)
                {
                    collection.findOne({ name : "bob"}, function(err, thing)
                    {                           
                        return thing;
                    });
                });
            }
        });
    });
}

问题是,db.open是一个异步调用(它不会阻塞),因此getAThing返回“
undefined”,我希望它返回查询结果。我确定我可以使用某种阻止机制,但我想知道执行此类操作的正确方法。


阅读 337

收藏
2020-07-07

共1个答案

一尘不染

没有办法使这种同步变得不可怕。正确的方法是getAThing接受回调函数作为参数,然后thing在可用时调用该函数。

function getAThing(callback)
{
    var db = new mongo.Db("mydatabase", server, {});

    db.open(function(err, db)
    {
        db.authenticate("myuser", "mypassword", function(err, success)
        {
            if (success)
            {
                db.collection("Things", function(err, collection)
                {
                    collection.findOne({ name : "bob"}, function(err, thing)
                    {       
                        db.close();                    
                        callback(err, thing);
                    });
                });
            }
        });
    });
}

节点7.6+更新

async/await现在提供了一种使用返回承诺的异步API(例如本机MongoDB驱动程序那样)时的同步
样式 编码方式。

使用这种方法,上面的方法可以写成:

async function getAThing() {
    let db = await mongodb.MongoClient.connect('mongodb://server/mydatabase');
    if (await db.authenticate("myuser", "mypassword")) {
        let thing = await db.collection("Things").findOne({ name: "bob" });
        await db.close();
        return thing;
    }
}

然后您可以从另一个async函数调用let thing = await getAThing();

但是,值得注意的是,它MongoClient提供了一个连接池,因此您不应该在此方法中打开和关闭它。相反,请MongoClient.connect在应用启动期间调用,然后将方法简化为:

async function getAThing() {
    return db.collection("Things").findOne({ name: "bob" });
}

请注意,我们不在await方法中调用,而是直接返回由返回的promise findOne

2020-07-07