I like to imagine async programming in terms of a restaurant server
and the kitchen staff. The server has tons of tables to serve and
tons of things to do, he leaves off orders with the kitchen staff so
that he/she can go on and serve other customers. The server can't
block right? There are a variety of ways the kitchen staff can alert
the server of problems with the order ranging from:
A) Yelling at the server the next time they see them - a callback,
pass the error.
B) Tell all the other staff to let them know the order is fucked -
emit an error.
C) Leave a note for them or tell the kitchen manager to tell them -
kind of like setting an error property on the kitchen.
D) Open the door to the restaurant and yelling at the server -
throwing an exception.
Of the 4 options, if I am not off my rocker, option D is obviously the
most disruptive and obnoxious. It basically sends a jolt through the
whole system. If this is true, then why do many node libs immediately
throw exceptions on errors instead of cycling through some of the
other options more carefully.
Example, you are writing a database driver. The database returns an
error, and you immediately throw an exception. But what about
considering that the clients of your lib might want to handle the
error, intelligently acting upon it within the context of a
transaction that is executing concurrently. In this case, setting a
lastError property, and then emitting an error seems smarter. If the
client has still not fixed it you can always throw it later.
Even a lib that has no async interface, could be used by a client in
an async way by wiring it up with async code.
Many of our libs should behave a bit more carefully about throwing
exceptions. Am I wrong?
// granted, you could just do fs.readFile("foo", cb),
// but the point is to show the pattern in action.
function readFoo (cb) {
fs.readFile("foo", function (er, data) {
if (er) return cb(er);
cb(null, data);
});
}
function readFooSync () {
// this will throw if it fails.
var data = fs.readFileSync("foo");
return data;
}
Consistently following this pattern allows you to do all kinds of very
creative chaining and error handling quite easily. Throwing in async
code is sloppy.
--i
> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>
>
// Same example but without using Conductor.// Note the level of error handling done automatically by Conductor.function loadArticle(name, callback) {try {var filename = path.join("articles", name + ".markdown");Git.readFile(filename, function (err, markdown) {if (err) {callback(err);return;}try {var props = markdownPreParse(markdown);props.name = name;loadAuthor(props.author, function (err, author) {if (err) {callback(err);return;}try {props.author = author;callback(undefined, props);} catch (err) {callback(err);}});} catch (err) {callback(err);}}} catch (err) {callback(err);}}
On Apr 5, 7:26 am, Tim Caswell <t...@creationix.com> wrote:
> Also, in Javascript with async code, it's not so much a question of form or preference, but the only way that error handling works consistently.
>
> Basically, the reason that sync functions throw exceptions is because functions can only return one value. It's a real pain to have to check the return value to see if it's an error message or a real return value. It's ok to throw exceptions if something exceptional happened and you can't give a meaningful response to the function request.
>
> Now, async code is a different beast all together. Because of the way try..catch works in JavaScript, it's impossible to catch any exceptions thrown inside the body of a callback function.
>
> See this thread and gist for more info on thathttp://groups.google.com/group/nodejs/browse_thread/thread/78ad347831...http://gist.github.com/292192
> >> For more options, visit this group athttp://groups.google.com/group/nodejs?hl=en.
Usually, callbacks have an error argument (usually, the first), that
will tell if something bad happened (or null/undefined otherwise).
Yeah, try/catch pretty ugly. Almost as ugly as doing sync file system IO :)
I always find your explanations/blog, code/comments and the demo above
quite helpful.
Thank you for sharing and taking the time.
cheers
--
shaun