mongodb crashed node with exception within try catch

try
    p = req.params.name
    Item.update('name': p, req.body , {upsert: true}, (err) ->
      if err?
        throw err
      res.send("ok")
      )
  catch e
    handle_error(e, "Error salvando hoja de vida.", res)

This produces an error in my code right now - that's alright, but why does my nodejs program crash even if I have a try catch here?

The error is:

MongoError: Mod on _id not allowed

(so it must be in the update call) I am specifically looking for a way to catch an error, I already know how to get rid of it.

Answers


Ah yes, you have entered the realm of asynchronous code. The reason you pass a callback into your MongoDB calls like Item.update(..., callback) is because the MongoDB driver is written to be asynchronous. Consider this (mongoose code):

var user = User.findOne({ name: 'joe' });
doSomethingElse();

If it had structured its API like the above code then your entire application would halt until User.findOne() returned the results from the database. Your doSomethingElse() call wouldn't be invoked until the user was retrieved, even if you don't do anything with user inside doSomethingElse. This is a big no no these days and especially in node which has been written to be asynchronous as much as possible. Have a look at the following:

User.findOne({ name: 'joe' }, function (err, user) {
    if (err) return console.error(err);
    console.log('Do stuff with user... ;)');
});
doSomethingElse();

The above code is asynchronous. The findOne function returns immediately and doSomethingElse is able to begin even before the user is ever retrieved from the database. But of course we still want to do stuff with our user, so in order to accomplish this we pass an anonymous function in to be used as a callback. The MongoDB driver is smart enough to call that function when it's all done retrieving data.

Wrapping the above code in a try/catch would be pointless, unless you suspected the findOne function to throw an exception (Which you shouldn't. It returns immediately remember?).

try {
    User.findOne({ name: 'joe' }, function (err, user) {
        throw new Error("Something went wrong...");
    });
} catch (err) {
    console.error(err);
}

The above error would still crash your program because it happened long after findOne returned and your program moved on way beyond that precious try/catch. This is the very reason why your callback function receives an err argument. The MongoDB driver knows that if some error occurs while fetching your data it would be no good to throw an exception and call it good. This is because all this processing has happened later on subsequent trips through the event loop, having left your try/catch behind several iterations ago.

To get around this the MongoDB driver wraps its own internal synchronous code in a try/catch where it actually will handle the exception and then it invokes your callback passing in the error as the first argument. This allows you to check that argument and handle any errors within your callback.

I wrote an entire blog post explaining callbacks, as well as another way of handling asynchronous code called "promises" and I think it would help clarify some things for you :) http://codetunnel.io/what-are-callbacks-and-promises

I hope that helps answer your question.


Maybe I'm wrong (because I don't know Coffeescript), but I suppose the problem is, that your try/catch is outside the callback function. The catch doesn't affect your err -> so the exception is not caught by you, but by node.js.

If I'm wrong, could you perhaps provide the compiled JavaScript code?

Edit

Usually one would handle the error more like this (without try/catch):

Item.update('name': p, req.body , {upsert: true}, (err) ->
  if err?
    log.error('error updating Item name=' + name)
    res.status(500).end()
    return
  res.send("ok")
  )

Probably your handle_error will do this already.

When programming in node.js, I use try/catch only for JSON.parse or if I have a lot of unchecked input which might have wrong types or might be null and I'm too lazy to check all input manually. Surrounding asynchronous functions with try/catch is only helpful if the function has programming errors (e.g. not checking your input correctly).


Need Your Help

Should the choice of programming language be a team decision or a management one?

programming-languages project-management project-planning

I just had a discussion with an employee of mine about the department programming language standard. He felt that the choice of the programming language should reside with the project team. I feel ...

How to fill the mysql table with other columns

mysql sql

I have a website using mysql and I have a question about sql syntax.