【问题标题】:JavaScript Code does not run in wanted order (Node.js, MongoDB)JavaScript 代码未按所需顺序运行(Node.js、MongoDB)
【发布时间】:2017-05-30 09:50:49
【问题描述】:

我知道 Node.js 的非阻塞 I/O 以及什么是异步函数,但我很难指出为什么这段代码运行起来像它运行一样。

我正在连接到 MongoDB 集合,搜索重复项,将第一个重复的值放入数组对象 (dupIndex) 中。 当数组打印时我看到 2 个值 (console.log(dupIndex);),但是当我稍后使用 .length 属性时看到 0 (console.log(dupIndex.length); em>) -- 当我真正期待 2 时。

我想继续并使用我在 dupIndex 中的数据来操作集合(例如使用 deleteMany 方法),但是如果它显示为 0,我不能,至少不是这样。有人可以解释一下并帮助我吗?

谢谢!

//connect us to a running MongoDB server
const {MongoClient, ObjectID} = require('mongodb');

var dataBase = "TodoApp";
//connecting to a database
//connects to the database /TodoApp, if no such db exists it auto creates it
MongoClient.connect(`mongodb://localhost:27017/${dataBase}`, (err, db)=>{
    if(err){
        //return or 'else' - so if an error happens, it won't continue
        return console.log(`Unable to connect. Error: ${err}`);
    }

    console.log(`Connected to MongoDB server. Database: ${dataBase}.`);
        var dupIndex = [];
    //find all
    db.collection('Todos')
    .find()
    .toArray().then((docs) => {
        for ( var i =0; i< docs.length -1; i++){
            for(var j =i+1; j< docs.length; j++){
                    if(docs[i].text === docs[j].text)
                    {   
                        console.log(`in`);
                        dupIndex.push(docs[i].text);
                        i++;
                    }
            }
        }
        console.log(dupIndex);

    }, (err)=> {
        console.log(`unable t o fetch`);
    });

    console.log(dupIndex.length);
    // for(var i = 0; dupIndex)
    //close the connection to the db
    db.close();
});

【问题讨论】:

    标签: javascript arrays node.js mongodb algorithm


    【解决方案1】:

    因为 console.log(dupIndex.length);在嵌套循环之前运行。

    db.collection('Todos')
    .find()
    .toArray()
    

    这是一个异步调用,控制权传递给 console.log(dupIndex.length); 尝试编写 console.log(dupIndex.length);在 console.log(dupIndex) 旁边;

    例如:

     db.collection('Todos')
    .find()
    .toArray().then((docs) => {
        for ( var i =0; i< docs.length -1; i++){
            for(var j =i+1; j< docs.length; j++){
                    if(docs[i].text === docs[j].text)
                    {   
                        dupIndex.push(docs[i].text);
                        i++;
                    }
            }
        }
        return dupIndex;
    }, (dupIndexRecieved)=> {
        console.log(dupIndexRecieved.length); data recieved here
    }, (err)=> {
        console.log(`unable t o fetch`);
    });
    

    【讨论】:

    • 感谢您的回复!是的,我目前了解,但非常模糊。你能解释一下为什么会发生在这里吗?我通常如何避免这种情况/将来使用它?
    • db.collection('Todos') .find() .toArray() 这个函数是异步的,所以当这个函数被调用时 node.js 事件循环向 mongoDB 发送数据请求,同时当请求由 MongoDB eventloop 娱乐将控制权传递给下一段代码,即 console.log(dupIndex.length);在您的情况下,当从 mongo 收到响应时,您的代码将被触发并填充您的数组。
    • 尝试更好地使用 Promises 并将结果传递到 Promise 链中 例如:
    【解决方案2】:

    //将我们连接到正在运行的 MongoDB 服务器

    const {MongoClient, ObjectID} = require('mongodb');
    
    var dataBase = "TodoApp";
    //connecting to a database
    //connects to the database /TodoApp, if no such db exists it auto creates it
    MongoClient.connect(`mongodb://localhost:27017/${dataBase}`, (err, db)=>{
    if(err){
        //return or 'else' - so if an error happens, it won't continue
        return console.log(`Unable to connect. Error: ${err}`);
    }
    
    console.log(`Connected to MongoDB server. Database: ${dataBase}.`);
        var dupIndex = [];
    //find all
    db.collection('Todos')
    .find()
    .toArray().then((docs) => {
        for ( var i =0; i< docs.length -1; i++){
            for(var j =i+1; j< docs.length; j++){
                    if(docs[i].text === docs[j].text)
                    {   
                        console.log(`in`);
                        dupIndex.push(docs[i].text);
                        i++;
                    }
            }
        }
    
        //Mongo db find returns a promise. The value you are accessing with the then function. So whatever you want to do with the db query return value you have to do it here inside the then function.
    
        console.log(dupIndex.length);
    
        console.log(dupIndex);
        // for(var i = 0; dupIndex)
        //close the connection to the db
        db.close();
    
    }, (err)=> {
        console.log(`unable t o fetch`);
    });
    
    //when you make the call here its get called before the then function. Thats why the length is zero. 
    
    });
    

    【讨论】:

    • 感谢您的回复!为什么在函数之前调用它? :s
    • 因为那是一个异步函数。当您调用异步函数时,它不会阻止它之后的代码。后面的代码可能会在异步函数的回调函数之前执行。异步函数完成后调用回调函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多