Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript anti-silent techniques to indicate failure

What would be a good way to report errors in JavaScript instead of relying on nulls, and undefineds when errors do occur and a function is unable to proceed forward. I can think of three approaches:

  1. do nothing
  2. throw an exception
  3. assert

Here's a simple example scenario - a function that credits a user account with the amount passed in. The function credit is part of an Account object.

Here's the naive solution.

function credit(amount) {
   this.balance += amount;
}

A major problem with this approach is invalid data. Let's fix it up, and use a return value to indicate that the operation failed.

function credit(amount) {
    if(!isInt(amount)) {
        return false;
    }
    this.balance += amount;
}

This is an improvement over the previous one, but client code will have to check the return value to ensure that the operation succeeded. Doing this for basically every method in the system can become cumbersome.

if(!johnDoe.credit(100)) {
    // do some error handling here
}

A third approach, similar to the second one, is to throw an exception. Since we are throwing the exception ourselves, could throw a specific type of exception rather than a general one.

function credit(amount) {
    if(!isInt(amount)) {
        throw new InvalidAmountError(amount);
    }
    this.balance += amount;
}

A fourth approach similar to throwing exceptions is to use assertions in your code. One shortcoming compared to the above approach is that since the assert is generic, we lose the ability to throw custom exceptions. It is still possible though by passing the object to throw in each assert call.

function credit(amount) {
    assert(!isInt(amount), "Amount to credit is not an integer");
    this.balance += amount;
}

A global assert function is easy to write and makes the code a little shorter.

function assert(value, message) {
    if(value !== true) {
        throw new AssertionError(message);
    }
}

function AssertionError(message) {
    this.message = message;
}

AssertionError.prototype.toString = function() {
    return 'AssertionError: ' + this.message;
}

Out of these approaches, what would be a good way to deal with unexpected values, and unhappy paths. Are there any other approaches not mentioned here that could be useful?

like image 464
Anurag Avatar asked Jul 17 '10 01:07

Anurag


People also ask

What is silent error in JavaScript?

Silent errors are errors that do not trigger any kind of reporting. They are usually indicated by function return values or can be detected by querying an error state. It is the responsibility of the developer to check for such errors and handle them (e.g. by generating an error message or writing them to a log file).

Is it good to use try-catch in JavaScript?

One of the benefits of try/catch is its ability to display your own custom-created error. This is called (throw error) . In situations where you don't want this ugly thing that JavaScript displays, you can throw your error (an exception) with the use of the throw statement.

What are the best practice of error handling in JS?

The most fundamental way of handling errors that have been thrown either manually or by the runtime is to catch them. Like most other languages, JavaScript offers a set of keywords to handle errors. It's essential to know each of them in-depth before you set down to handle errors in your JavaScript app.


2 Answers

Consider a client-side logging framework to report errors, such as Log4js. One can log messages (i.e., info, debug, warn, error) in the browser or persist messages to the server via Ajax, depending on the application.

The Log4js site also provides a list of other JavaScript logging frameworks.

A good approach, using your custom exception example, would be to throw the exception and log the error as you see fit.

like image 58
Chocula Avatar answered Nov 01 '22 22:11

Chocula


One shortcoming compared to the above approach is that since the assert is generic, we lose the ability to throw custom exceptions

Not necessarily:

function assert(value,message,Exctype) {
    if(value !== true) throw new Exctype(message);
}

Constructors are functions. Functions are first class values. Feel free to pass 'em around.

like image 22
Weston C Avatar answered Nov 01 '22 22:11

Weston C