Search code examples
node.jsmongodbexpressmongoosecloud9-ide

mongodb Dog.find() is executing before Dog.create()


mongodb Dog.find() is executing before Dog.create()

i just have a some problem that i can't understand as so why its happening. I just started learning mongodb with online tutorial.I practice my code at cloud9. I was practicing the basic queries such as find() and create(). i added the Dog.create() method first by adding a new dog with just a name parameter and the subsequently below the create() method i added Dog.find() to find all the data present in the db.

But the problem is Dog.find() executes first and the Dog.create executes at last.

I have posted the code below.

var mongoose= require("mongoose");
mongoose.connect("mongodb://localhost/dog_app");

var dogSchema = new mongoose.Schema({
  name:String
});

var Dog = mongoose.model("Dog", dogSchema);

Dog.create({
    name:"duppy"
}, function(err, dog){
    if(err){
        console.log(err);
    }else{
        console.log("created a new dog");
        console.log(dog);
    }
});

Dog.find({}, function(err , dogs){
   if(err){
       console.log(err);
   } else{
       console.log("retrived from database");
       console.log(dogs);
   }
});

Results

adi188288:~/workspace/IntroToNode/Databases $ node dogs.js
(node:7113) DeprecationWarning: `open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client
retrived from database
[ { _id: 59bd6256bffba3198bce7e87, name: 'Puppy', __v: 0 } ]
created a new dog
{ __v: 0, name: 'Puppy2', _id: 59bd6932a2d4c81bc9488b74 }

You can see the results that first the find method is executing and then a create method occurs.Can Anyone Explain this to me?


Solution

  • You've created a race condition. Both calls are asynchronous, meaning they don't return immediately, they have to wait for the database to complete its operation. However, you're executing both calls in parallel by doing it in the same tick.

    Basically your code sends two requests to MongoDB; one that it creates a dog and the other looks for the dogs. MongoDB processes both in parallel, and sends back the result of both. In this case find call took less time so it called it's callback first.

    If you want one to execute after the other you have to put them in the callback. The callback will only be called once the async operation is complete:

    Dog.create({
        name:"duppy"
    }, function(err, dog){
        if(err){
            console.log(err);
        }else{
            console.log("created a new dog");
            console.log(dog);
    
            Dog.find({}, function(err , dogs){
               if(err){
                   console.log(err);
               } else{
                   console.log("retrived from database");
                   console.log(dogs);
               }
            });
        }
    });
    

    You may also want to use promises instead as suggested by alexmac:

    Dog.create({
        name:"duppy"
    }).then(function(dog){
      console.log("created a new dog");
      console.log(dog);
      return Dog.find({});
    }).then(function(dogs){
      console.log("retrived from database");
      console.log(dogs);
    });
    

    Or you can even use async/await.