Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle synchronous exceptions better #85

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Handle synchronous exceptions better #85

wants to merge 1 commit into from

Conversation

ForbesLindesay
Copy link
Contributor

Same as #83 but with a fixed diff

*/
function handleErrors(fn) {
return function (str, options, cb) {
var finished = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does finished do? Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It prevents the callback being called multiple times. For example:

cons.temp.render = function (str, opts, cb) {
  try {
    cb(new Error('this never goes well');
  } catch (ex) {
    cb(ex);
  }
};

cons.temp.render('', {}, function (err, res) {
  console.log('There was an error');
  throw err;
});

In there the console.log will be hit twice:

There was an error
There was an error

Error: this never goes well
  Stack Trace
  Stack Trace
  Stack Trace
  Stack Trace

This kind of bug exists in reality in lots of places in the code and it's really hard to debug, so it's easiest to just fix it at the top level.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just

try {
  var result = engine.render(str, options);
} catch (err) {
  return fn(err);
}
fn(null, result);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can for synchronous parsers, and that's always sufficient for the synchronous parsers, but it does nothing to prevent poorly implemented async templating libraries.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't even know how it's possible to make a synchronous parser in node .. and that's why I'm curious why most of the engines don't have a callback for it's compile/render functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only thing that would force you to make your template parsing async is if you allow users to do async work inside their templates. Node.js can do pretty much anything synchronously if you want it to (making http web requests takes a bit of work). Most of the libraries just transform strings to functions so there's no real reason for there to be any async work there.

P.S. The only two that actually operate asyncronously are dust and qejs the rest just trick you into thinking they do by providing a node style apie when in fact their syncronous (for an example take a look at the source code for the render function for jade no Async there P.S. it also nicely demonstrates a template library that suffers from the problem finished would fix.)

@doowb
Copy link
Collaborator

doowb commented Sep 17, 2017

I know this is old, and with the promise support that has been added, it might not be an issue. If it is, then I think we can add this logic to the promisiify function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants