try-catch-finally.js
843 byte library for more flexible error catching in JavaScript.
Contents
Installation
Browser
<script src="try-catch-finally.js"></script>
console.log(typeof window.try) // -> function
console.log(typeof window._try) // -> function
AMD
define(['try-catch-finally'], function (_try) {
console.log(typeof _try); // -> function
});
Node
npm install --save try-catch-finally
var _try = require('try-catch-finally');
console.log(typeof _try); // -> function
Usage
API
_try ( tryBlock )
- tryBlock
<function>
- code which may throw errors
.catch ( [ error, ] handleError )
- error
<any>
- (optional) error to catch - handleError
<function>
- handle errors which correspond to error (if defined); else handle any error
.finally ( finallyBlock )
- finallyBlock
<function>
- code which will always exectue
Examples
Catch anything
_try(function () {
throw new Error('boom');
})
.catch(function (e) {
console.log('Caught', e);
});
Catch-by-value
_try(function () {
throw 12345;
})
.catch(12345, function (e) {
console.log('Caught', e);
});
Error value matches by strict equality (===
).
Catch-by-name
_try(function () {
throw { error: 'boom' };
})
.catch('object', function (e) {
console.log('Caught', e);
});
Error name matches similarly to typeof
, with the bonus that it:
- is case-insensitive
- works for boxed primitives (e.g.
new String()
)
Catch-by-type
_try(function () {
throw 'boom';
})
.catch(Object, function (e) {
console.log('Caught', e);
});
_try(function () {
throw new TypeError('boom');
})
.catch(Error, function (e) {
console.log('Caught', e);
});
Error type matches similarly to instanceof
, with the bonus that it works for literal primitives ('hello'
, 123
, etc).
Caveats
Catch-by-name may not work
It's not always possible to get the name of an object in JavaScript, such as for objects created using non-native constructors:
function CustomError() {}
_try(function () {
throw new CustomError();
})
.catch('CustomError', function (e) {
console.log('Caught', e);
});
Or for some native objects which use inheritance:
_try(function () {
throw new TypeError();
})
.catch('TypeError', function (e) {
console.log('Caught', e);
});
Those catch blocks won't execute. The best this library can do is find out that:
- the
new CustomError()
is some kind ofobject
, but not specifically aCustomError
by name - the
new TypeError()
is some kind ofError
, but not specifically aTypeError
by name
It's best to use the catch-by-type style in those cases.
Catch-by-type won't work across frames/processes
This quirk exists in the native instanceof
(which fails across browser frames and node processes) when the instance's constructor differs to the one passed to instanceof
. It's best to use the catch-by-name in those cases.
Errors are consumed
Any error thrown synchronously in the try block is consumed by this library. There are two ways to ensure errors which aren't caught/handled by any catch
don't disappear:
Use an indiscriminate catch block
_try(function () {
throw new Error('boom');
})
.catch(String, function (e) {
console.log('Caught String', e);
})
.catch(function (e) {
console.log('Caught other', e);
});
The first catch block won't execute and the second ensures other errors don't go unhandled.
Use a finally block
_try(function () {
throw new Error('boom');
})
.catch(String, function (e) {
console.log('Caught', e);
})
.finally();
That catch block won't execute and the finally call ensures any caught error is re-thrown.
Tests
The following tests are continually run in TravisCI:
Node (v0.12, 4, 6, 8, 10) | Chrome Headless (global) | Chrome Headless (AMD) | |
---|---|---|---|
unminified | ☑ | ☑ | ☑ |
minified | ☑ | ☑ | ☑ |
The tests can be run in any browsers supported by Karma. See the npm scripts and travis configuration for more details.