user3188325
user3188325

Reputation: 35

MongoDB Node.js driver: callback does not handle exceptions on insert

w3school gives a simple example of inserting an object into a database, but in this example the callback seems not to catch some exceptions and I cannot understand why.

On this modified example,

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/mydb";

MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  // var myobj = { name: "Company Inc", address: "Highway 37" };
  var myobj;       // undefined
  db.collection("customers").insertOne(myobj, function(err, res) {
    if (err) console.log('Error: We should see this');
    console.log("1 document inserted");
    db.close();
  });
});

I am trying to insert an undefined object into a collection and expect the callback to handle the exception by printing out the text ('Error: We should see this').

Instead, the following exception is thrown and the program terminates (as if the whole connect expects to be wrapped by try/catch block).

TypeError: Cannot read property '_id' of undefined

Can someone, please, explain why this is happening?

Thanks!

Upvotes: 2

Views: 1872

Answers (1)

Kirk Larkin
Kirk Larkin

Reputation: 93053

Before running the actual insertOne command against the MongoDb server, the _id property of the document you are trying to insert is accessed to see if it is currently 0. You can see this happening in the source code.

The key point here is that this is before the asynchronous processing of the insertOne request begins - The error has not occurred during the actual insert process, but rather during a pre-check on the doc argument. The code assumes that you have not provided a null/undefined document, which in this case is not a correct assumption.

Obviously, you can check the document before you pass it in - ensuring that it is not null/undefined - This would be sensible. Otherwise, you could wrap just the insertOne call in a try/catch:

MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    // var myobj = { name: "Company Inc", address: "Highway 37" };
    var myobj;       // undefined

    try {
        db.collection("customers").insertOne(myobj, function(err, res) {
            if (err) console.log('Error: We should see this');
            console.log("1 document inserted");
            db.close();
        });
    } catch (e) {
        ...
    }
});

I'd go with the approach of checking the document is valid before sending it into insertOne. You have full control of this and wouldn't need the try/catch.

In summary, the approach you show is somewhat of a misuse of the driver.

Upvotes: 2

Related Questions