2

I know about Node.js's non blocking I/O and what are async functions but I'm having trouble to point down why this code runs like it runs.

I'm connecting to a MongoDB collection, searching for duplicates, putting the first values that repeat themselves in an array object (dupIndex). I see 2 values when the array prints (console.log(dupIndex);), but 0 when I use the .length property later (console.log(dupIndex.length);) -- when I'm actually expecting 2.

I would like to continue and manipulate the collection with the data I have in dupIndex (like use deleteMany method), but if it shows 0, I can't, at least not like this. Can someone explain this and help me with this?

Thanks!

//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();
});

2 Answers 2

2

Because console.log(dupIndex.length); runs before your nested loops.

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

This is an async call and control is passed to console.log(dupIndex.length); try writing console.log(dupIndex.length); next to console.log(dupIndex);

For Example:

 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`);
});
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the reply! Yes, that I understand so far, but very vaguely. Can u explain why exactly it happens here? How can I generally avoid this/use it in the future?
db.collection('Todos') .find() .toArray() This function is async so when this function is called node.js event Loop send a request to mongoDB for data and meanwhile when request is entertained by MongoDB eventloop pass the control to next piece of code that is console.log(dupIndex.length); in your case when response is recieved from mongo your code inside then is triggered and populates your array.
Try Using Promises better and pass the result in prosmise chain For Example:
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++;
                }
        }
    }

    //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. 

});

2 Comments

Thanks for the reply! why does it get called before the function? :s
Because thats a async function. When you call a async function it does not block the code after it. The later code might gets executed before the callback function of the async function. The call back function is called once the async function is done.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.