开发者

JavaScript try/catch: errors or exceptions?

OK. I may be splitting hairs here, but my code isn't consistent and I'd like to make it so. But before I do, I want to make sure I'm going the right way. In practice this doesn't matter, but this has been bothering me for a while so I figured I'd ask my peers...

Every time I use a try... catch statement, in the catch block I always log a message to my internal console. However my log messages are not consistent. They either look like:

catch(err) {
DFTools.console.log("someMethod caught an error: ",err.message);
...

or:

catch(ex) {
DFTools.console.log("someMethod caught an exception: ",ex.message);
...

Obviously t开发者_StackOverflowhe code functions properly either way but it's starting to bother me that I sometimes refer to "errors" and sometimes to "exceptions". Like I said, maybe I'm splitting hairs but which is the proper terminology? "Exception", or "Error"?


This is a bit subjective, but to me an error is when someone or something does something wrong, improper, or invalid. It could be a syntax error, a logical error, a read error, user error, or even a social error. It's an abstract concept.

An exception, on the other hand, is an object that is created and thrown when a certain condition occurs in code. It may or may not correspond to a conceptual error. So to me, the proper nomenclature is "exception".


The ECMAScript specification calls them exceptions. You might want to do likewise.

To make your logging more informative:

catch(ex) {
    DFTools.console.log("someMethod caught an exception of type " 
       + ex.name + ": ", ex.message);

You might also want to bear in mind that exceptions (unfortunately) can be of any type, and so don't necessarily have name and message properties:

catch(ex) {
    if (ex.message && ex.name) {        
        DFTools.console.log("someMethod caught an exception of type " 
           + ex.name + ": ", ex.message);
    } else /* deal with it somehow */

As this is starting to look pretty cumbersome to repeat everywhere, you might want to capture it in a function:

function logExceptions(methodName, action) {

    try {

        action();

    } catch (ex) {
        if (ex.message && ex.name) {        
            DFTools.console.log("someMethod caught an exception of type " 
               + ex.name + ": ", ex.message);
        } else {
            DFTools.console.log("someMethod caught a poorly-typed exception: " + ex);
        }
    }
}

Now you can say:

logExceptions(function() {

    // do some risky stuff...

});


In JavaScript it is called Error Catching. So I would suggest you use error instead of exception. Leave the choice in the middle by using "e". Like in the examples of Mozilla. Mozilla Core JavaScript 1.5 Reference


Exception is something you may expected for example in an attempt to open a file may face a "File not found exception". On the other hand, errors are something you may not see it coming like stack over flow or not enough memory.

An exception is an alternative logical way out off a function that does not produce a logical result. An exception also allows a better explanation of what happen why it exist this way. For File opening, again, a file handle is a logical result and if the file is not exist (one possible exception) or it is a folder not a file (another possible exception).


MAJOR DISCLAIMER: I don't consider that there is a "right" answer to this. The views expressed here are subjective and personal. What's more is that the ideas I'm about to espouse are only useful if you are going to do different things with different, ahem, faults... as you might using a system as per Daniel Earwicker's informative answer. With that in mind:

I contend that "an EXCEPTION is exceptional". An ERROR is less unexpected.

disclaimer: The following pseudo-code is not good; it merely serves as the minimum case I could think of to illustrate my point.

note: in this thought experiment, GetFile returns UNDEFINED if it cannot find the specified file.

function AlwaysGetFile(name){
    var file = null;
    if(FileExists(name)){
        file = GetFile(name);
        if(typeof file === "undefined"){
            throw new "couldn't retrieve file" EXCEPTION
        }
    }
    else{
        throw new "file does not exist" ERROR
    }
    return file;
}

In the case that a consumer calls GetFileOrThrow with a filename that doesn't exist, an ERROR will occur. To my mind the distinction is really that higher-level code (or user input) is doing something wrong... this function must pass an ERROR up the line to that higher-level code which can decide what to do about this result. Consider it like this... this function would be saying to any consuming functions:

Look, my friend, I know what's going on here: it is an ERROR to request BobAccounts.xml, so don't do it again! Oh, and if you think you now know what might have gone wrong (having abused me), go ahead and try to recover from it!

Now consider the case that this function takes the name, checks that the file exists and then for some reason fails to retrieve it. This is a different situation. Something really unexpected has happened. What's more, the consuming code isn't to blame. Now we really want this function to say to any consuming functions:

Oh fiddlesticks! Sorry about this, I humbly beg your pardon but something EXCEPTIONAL that I don't really understand has gone wrong. I don't think that your request for BobAccounts.xml was unreasonable... and I know I should be fulfilling it for you. Since I'm lower level code than you, I really ought to know what's going on... but I don't... and since you've less chance than me of understanding this EXCEPTIONAL situation, I think you'd probably best just stop what you're doing and let this message go all the way to the top... I mean, there is something seriously fishy going on here.

So I suppose my summary is this: If the mistake happened in higher order code (you were passed bad data) throw an ERROR. If the mistake happened in lower order code (a function you depended on failed in a way you didn't understand and couldn't plan for) throw an EXCEPTION... and if the mistake happened in the function you are currently writing... well, duh, if you're aware of it then fix it!

And, finally, to answer the original question more directly: In terms of handling ERRORS and EXCEPTIONS, my advice would be: Handle all ERRORS gracefully (optionally logging them)... but handle EXCEPTIONS carefully indeed; only try to recover from an EXCEPTION if you are really sure you know what it is and why it's happened, otherwise let it bubble up (rethrowing it if you have to).


What you get in a Catch block is an Exception, so I name it as an exception...

If it is an error - I can handle it in my code & I usually don't expect to see it in the Catch block

HTH.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜