JSPM

  • Created
  • Published
  • Downloads 304
  • Score
    100M100P100Q88103F
  • License MIT

Errors that you can catch by type.

Package Exports

  • interrupt

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (interrupt) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Build Status Coverage Status

TODO: Refactor this diatribe. I don't care about type anymore. JavaScript and espeically Node.js is not so terribly mysterious that you cannot guess what will be thrown. Adding an interrupt property would be enough, I believe, to make sure you catch this exception by type.

First, this is about Node.js.

Let me tell you about this assuming Node.js. When you throw a message, you want everything you'd hope the user would tell you about the error in the stack. The stack will get dumped to standard out by the default exception handler. This is what is most likely to come your way in a GitHub issue. It is what is mostly likely to be written to a log message.

And then...

It's advantage is the lengths it will go to to preserve context and make a meaningful stack message. I've found that the context I desire for these exceptions must be captured when thrown. The message you'd want to see in a log message, the message you want to see in a user's bug report must be formatted and ready to go. It must be the likely message. You can't put the necessary information in the exception so that a message might be formatted if the user so chooses. You want to smash as much information in stack so that the likely outcome is.

Then maybe it is about Browserify.

This will work in the browser, but it does depend upon util.inspect.

Errors that you can catch by type.

Interrupt is part of the Cadence Universe. Cadence provides a robust asynchronous try/catch mechansism. Thus, I use try/catch error handling in all my evented Node.js programs.

When you throw an exception in any other language, you're able to catch those exceptions by type, so that you only handle the exceptions you know how to handle.

You can't catch exceptions by type in JavaScript. The best you can do is check the error message. There is no real way to indicate an exception type that was thrown deep within your code.

With Interrupt you can add namepsaces to your exceptions and catch specific exceptions based on namespace and by matching the message.

Synopsis

var assert = require('assert')
var interrupt = require('interrupt').createIterruptor('bigeasy.example')

try {
    throw interrupt(new Error('convert'), { value: 1 })
}  catch (error) {
    interrupt.rescue('bigeasy.example.convert', function () {
        assert.equal(error.value, 1)
    })(error)
}

In the above example we create an interrupt instance to use in our module providing a namespace that will be used to distinquish our errors. The naming convention for interrupt is your GitHub name and the name of the project.

We create a new exception by calling interrupt, passing a new Error with a message that is used to distinguish the error. You can also provide a map of properties that will be added to the error for context.

In the catch block we call interrupt.rescue() with a pattern to match the specific exception. The pattern will match the combination of the interrupt namespace and exception message. If the pattern matches, then the exception is caught. If it does not match, the exception is rethrown.

Unambiguous Exceptions

What if you want to catch an exception from a third party library. You use a try/catch block to choke up on the point of failure and wrap the result in an interupt.

var assert = require('assert')
var interrupt = require('interrupt').createIterruptor('bigeasy.example')

try {
    try {
        library.frobinate(1)
    } catch (error) {
        // almost certainly a frobination exception.
        throw interrupt(new Error('frobinate'), { cause: error })
    }
    library.doManyOtherThings()
} catch (error) {
    interrupt.rescue('bigeasy.example.frobinate', function (error) {
        console.log('frobination failure')
        console.log(error.cause.stack)
    })(error)
}

In the above example we've put a catch block around the operation we know might fail, that we know how to recover from, but rather than try and guess the error in some remove catch block when it has unwound the stack, we immediately wrap it in using interrupt. The rescue function will only catch Interrupt exceptions, it will rethrow all others.

In my programs, I find that the two patterns above make try catch useful again.

Selecting Exceptions

var assert = require('assert')
var interrupt = require('interrupt').createIterruptor('bigeasy.example')

try {
    if (!library.frobinate(1)) {
        throw interrupt(new Error('forbinate', { frobination: 1 })
    }
    if (!library.reticulate()) {
        throw interrupt(new Error('reticuate'))
    }
} catch (error) {
    interrupt.rescue([
        'bigeasy.example.frobinate', function (error) {
            console.log('frobination failure: ' + error.frobination)
        },
        'bigeasy.example.reticulate', function () {
            console.log('reticuation failure')
        },
        'bigeasy.example', function () {
            console.log('other library failure')
        }
    ])(error)
}

With Cadence

When combine with Cadence, I have robuts asynchronous try/catch with unambiguous error handling.

function Service (processor) {
    this._processor = processor
}

Service.prototype.serve = cadence(function (async, file) {
    async([function () {
        async([function () {
            fs.readFile(file, 'utf8', async())
        }, function (error) {
            throw interrupt(new Error('readFile'), { cause: error, file: file })
        }], function (file) {
            this._processor.process(file, async())
        })
    }, function (error) {
        interrupt.rescue('bigeasy.serivce.readFile', function (error) {
            console.log('cannot read file: ' + error.file)
        })(error)
    }])
})

The above example shows how we can catch an error locally, then wrap it so that we know to catch it in the outer most rescue loop. In this example, it would be better to log and return, but imagine if you will a much more complicated example where the file read is nested deeply in the call stack.