H
H
homm2011-02-09 09:13:24
Node.js
homm, 2011-02-09 09:13:24

Node.js (or other asynchronous frameworks): How to catch errors?

Here is a question. Maybe my stiff synchronous brain just doesn't see the solution that lies on the surface. But I don't understand how to handle errors with an asynchronous approach, how to issue a 500 page to the user. After all, how does the usual synchronous request work (schematically):

try {
  responce = (function request(req) {
    var user = auth.getUser(req);
    if (user.auth) {
      var data = db.getData();
      if (data) {
        return new Responce(template.render(data));
      }
    }
    return error404;
  })(req);
} catch(e) {
  show500(e);
}


Everything is very reliable, the controller must return a response, any errors that are not caught inside the request are caught outside and give the user a beautiful page.

What about the asynchronous approach of node.js?
try {
  (function request(req, res) {
    auth.getUser(req, function(user) {
      if ( ! user.auth) {
        return res.error404();
      }
      db.getData(function(data) {
        if ( ! data) {
          return res.error404();
        }
        res.write(template.render(data));
      });
    });
  })(req, res);
} catch(e) {
  res.show500(e);
}


And now imagine that somewhere in user.auth an exception occurs. What will happen? And nothing, function(user) will stop execution, there is no one to process the response, the connection with the browser will remain hanging until the timeout. Even by putting a global error handler somewhere, it will not be possible to return a response to the user, because the exception object itself does not have access to the request and response objects.

Really, the only way out is to catch exceptions manually on each asynchronous call?
try {
  (function request(req, res) {
    auth.getUser(req, function(user) {
      try {
        if ( ! user.auth) {
          return res.error404();
        }
        db.getData(function(data) {
          try {
            if ( ! data) {
              return res.error404();
            }
            res.write(template.render(data));
          } catch(e) {
            res.show500(e);
          }
        });
      } catch(e) {
        res.show500(e);
      }
    });
  })(req, res);
} catch(e) {
  res.show500(e);
}

Answer the question

In order to leave comments, you need to log in

6 answer(s)
A
Alexander Keith, 2011-02-09
@tenbits

I have an indirect relationship with node.js, but it always seemed to me that:

  • by all means avoid throwing exceptions, and return the error status
  • the asynchronous function call should look like this:
    asyncFunction(args, function(error, result){})
And now, if we translate these points into your code:
auth.getUser(req, function(error,user) {
  if (error != null){
    handle(res,error);
    return;
  }
  db.getData(function(error,data) {
    if (error != null){
      handle(res,error);
      return;
    }
  res.write(template.render(data));
});

The exception checks here seem redundant to me. The weak point is only template.render(data), you just need to check if this function throws exceptions. And even if so, it's better to check if the data object is valid before passing it to render. While I myself adhere to the rule, if a function needs more than 2/3 ifs for its normal operation, then only try..catch. Unfortunately, Javascript doesn't handle exceptions as flexibly as .NET does (sigh). I would also be happy if someone offers a more constructive answer.

A
akzhan, 2011-02-09
@akzhan

Take a look at thechangelog.com/post/516202796/step-control-flow-the-node-js-way
Just uniform error and exception handling.

Z
zohkiller, 2013-11-14
@zohkiller

We use domain http://habrahabr.ru/post/147233/

In general, the specifics of processing on a node is callback(error, data) where an error flies to the callback

J
Jazzist, 2011-02-10
@Jazzist

Firebag - a mega-popular plugin for Mozilla Firefox, perfectly solves just this problem:
- in the console you see all incoming and outgoing requests
- you see the content of these requests
- you see how HTML and CSS change
- you see errors, incl. server error messages
- ...
Firebag is installed from the Mozilla Firefox menu->Edit->Preferences->Add-ons->Configure add-ons->Search for add-ons

B
betula, 2014-07-21
@betula

I advise you to look towards co, koa.

A
Alexander Lozovyuk, 2011-02-09
@aleks_raiden

generate an event everywhere - type error_500, and stop working. and in the event handler you already form a response to the user and display it. then in any code it is enough to generate an event and the user will have the desired page

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question