JavaScript - Errors and logging

Error logging - Robust Client-Side JavaScript

The standard approach is to monitor all exceptions on a page and to handle them centrally, for example using window.onerror. Then gather a bunch of context information and send an incident report to a log server. That server stores all reports, makes them accessible using an interface and probably sends an email to the developer.

Here is a simple global error reporter:

Code language: JavaScript

window.onerror = function(message, file, line, column, error) {
  var errorToReport = {
    type: error ? error.type : '',
    message: message,
    file: file,
    line: line,
    column: column,
    stack: error ? error.stack : '',
    userAgent: navigator.userAgent,
    href: location.href
  };
  var url = '/error-reporting?error=' +
    JSON.stringify(errorToReport);
  var image = new Image();
  image.src = url;
};

This code sends a report to the address /error-reporting using a GET request.

The example above is not enough. It is not that easy to compile a meaningful, cross-browser report from an exception. Tools like TraceKit and StackTrace.js help to extract meaning from exceptions.

Quoted content by Mathias Schäfer is licensed under CC BY-SA. See the other snippets from Robust Client-Side JavaScript.

Strict Mode - Robust Client-Side JavaScript

ECMAScript 5 (2009) started to deprecate error-prone programming practices. But it could not just change code semantics from one day to the next. This would have broken most existing code.

In order to maintain backwards compatibility, ECMAScript 5 introduces the Strict Mode as an opt-in feature. In Strict Mode, common pitfalls are removed from the language or throw visible exceptions. Previously, several programming mistakes and bogus code were ignored silently. The Strict Mode turns these mistakes into visible errors – see failing fast.

Enable the Strict Mode by placing a marker at the beginning of a script:

Code language: JavaScript

'use strict';
window.alert('This code is evaluated in Strict Mode! Be careful!');

Or at the beginning of a function:

Code language: JavaScript

function strictFunction() {
  'use strict';
  window.alert('This function is evaluated in Strict Mode! Be careful!');
}

Syntax-wise, 'use strict'; is simply an expression statement with a string literal. This code does not do anything when evaluated. It is a meaningful marker for browsers that support ECMAScript 5, and innocuous code for browsers that do not.

Quoted content by Mathias Schäfer is licensed under CC BY-SA. See the other snippets from Robust Client-Side JavaScript.

NaN is contagious - Robust Client-Side JavaScript

NaN is a dangerous beast. NaN is a special value that means “not a number”, but in fact it is a number you can calculate with.

NaN is contagious. All calculations involving NaN fail silently, yielding NaN: 5 + NaN makes NaN, Math.sqrt(NaN) produces NaN. All comparisons with NaN yield false: 5 > NaN is false, 5 < NaN is also false. 5 === NaN is false, NaN === NaN is also false.

If a NaN slips into your logic, it is carried through the rest of the program until the user sees a “NaN” appearing in the interface. It is hard to find the cause of a NaN since the place where it appears can be far from the place that caused it. Typically, the cause of a NaN is an implicit type conversion. My advice is to raise the alarm as soon as you see a NaN.

Quoted content by Mathias Schäfer is licensed under CC BY-SA. See the other snippets from Robust Client-Side JavaScript.

Failing fast - Robust Client-Side JavaScript

Every computer program may have logic bugs: A case is not considered, the state is changed incorrectly, data is transformed wrongly, input is not handled. These bugs can have several consequences in JavaScript:

In the best case the script fails with an exception. You may wonder, why is that the best case? Because an exception is visible and easy to report. The line of code that threw an exception is likely not the root cause, but the cause is somewhere in the call stack. An exception is a good starting point for debugging.

In the worst case the application continues to run despite the error, but some parts of the interface are broken. Sometimes the user gets stuck. Sometimes data gets lost or corrupted permanently.

JavaScript code should fail fast (PDF) to make errors visible. Failing early with an exception, even with a user-facing error, is better than failing silently with undefined, puzzling behavior.

Unfortunately, JavaScript does not follow the principle of failing fast. JavaScript is a weakly typed language that goes great lengths to not fail with an error.

[…]

The key to failing fast is to make your assumptions explicit with assertions.

Quoted content by Mathias Schäfer is licensed under CC BY-SA. See the other snippets from Robust Client-Side JavaScript.