Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error handling in asynchronous node.js calls

I'm new to node.js although I'm pretty familiar with JavaScript in general. My question is regarding "best practices" on how to handle errors in node.js.

Normally when programming web servers, FastCGI servers or web pages in various languages I'm using Exceptions with blocking handlers in a multi-threading environment. When a request comes in I usually do something like this:

function handleRequest(request, response) {   try {      if (request.url=="whatever")       handleWhateverRequest(request, response);     else       throw new Error("404 not found");    } catch (e) {     response.writeHead(500, {'Content-Type': 'text/plain'});     response.end("Server error: "+e.message);   } }  function handleWhateverRequest(request, response) {   if (something)      throw new Error("something bad happened");   Response.end("OK"); } 

This way I can always handle internal errors and send a valid response to the user.

I understand that with node.js one is supposed to do non-blocking calls which obviously leads to various number of callbacks, like in this example:

var sys    = require('sys'),     fs     = require('fs');  require("http").createServer(handleRequest).listen(8124);  function handleRequest(request, response) {    fs.open("/proc/cpuinfo", "r",     function(error, fd) {       if (error)         throw new Error("fs.open error: "+error.message);        console.log("File open.");        var buffer = new require('buffer').Buffer(10);       fs.read(fd, buffer, 0, 10, null,         function(error, bytesRead, buffer) {            buffer.dontTryThisAtHome();  // causes exception            response.end(buffer);         }); //fs.read      }); //fs.open  } 

This example will kill the server completely because exceptions aren't being catched. My problem is here that I can't use a single try/catch anymore and thus can't generally catch any error that may be raised during the handling of the request.

Of course I could add a try/catch in each callback but I don't like that approach because then it's up to the programmer that he doesn't forget a try/catch. For a complex server with lots of different and complex handlers this isn't acceptable.

I could use a global exception handler (preventing the complete server crash) but then I can't send a response to the user since I don't know which request lead to the exception. This also means that the request remains unhandled/open and the browser is waiting forever for a response.

Does someone have a good, rock solid solution?

like image 719
Udo G Avatar asked Apr 28 '11 09:04

Udo G


People also ask

How would you handle errors for async code in node JS?

If we want to handle the error for asynchronous code in Node. js then we can do it in the following two manners. Handle error using callback: A callback function is to perform some operation after the function execution is completed. We can call our callback function after an asynchronous operation is completed.

How do you handle error in async await in node JS?

You should handle unexpected errors in your async functions in the calling function. The run() function shouldn't be responsible for handling every possible error, you should instead do run(). catch(handleError) .

Which is the proper way to handle asynchronous errors in Express?

To handle an error in an asynchronous function, you need to catch the error first. You can do this with try/catch . Next, you pass the error into an Express error handler with the next argument. If you did not write a custom error handler yet, Express will handle the error for you with its default error handler.


2 Answers

Node 0.8 introduces a new concept called "Domains". They are very roughly analogousness to AppDomains in .net and provide a way of encapsulating a group of IO operations. They basically allow you to wrap your request processing calls in a context specific group. If this group throws any uncaught exceptions then they can be handled and dealt with in a manner which gives you access to all the scope and context specific information you require in order to successfully recover from the error (if possible).

This feature is new and has only just been introduced, so use with caution, but from what I can tell it has been specifically introduced to deal with the problem which the OP is trying to tackle.

Documentation can be found at: http://nodejs.org/api/domain.html

like image 119
Sam Shiles Avatar answered Oct 01 '22 12:10

Sam Shiles


Checkout the uncaughtException handler in node.js. It captures the thrown errors that bubble up to the event loop.

http://nodejs.org/docs/v0.4.7/api/process.html#event_uncaughtException_

But not throwing errors is always a better solution. You could just do a return res.end('Unabled to load file xxx');

like image 43
3rdEden Avatar answered Oct 01 '22 13:10

3rdEden