Knu
Knu

Reputation: 15134

How to handle multiple errors thrown by an utility function?

I have a function examples(a,b,c,…). Each argument can throw an error. All of them are handled the same way. I guess examples([array]) would fall in the same category.

In my code I have something like that currently:

  for (i = 0; i < len; i++) {
    try { this.example(arg[i]) }
    catch (e) { log(e) }
  }

From an user perspective Id like to be able to see the errors of all arguments at once instead of fixing one and then discovering the next one etc. But I end up catching myself which seems, to me, not desirable for an utility function.

Is there a way to rethrow all errors at once?

What are the best practices?

If there's a standard, why is it being recommended?

Upvotes: 0

Views: 1767

Answers (1)

Paul S.
Paul S.

Reputation: 66354

Well you can throw pretty much anything, but rather than just a simple Array, you may find you have more maneuverability using a custom error type

function ErrorCollection(msg) {
    this.name = 'ErrorCollection';
    this.message = msg || '';
    this.errors = [];
}
ErrorCollection.prototype = Object.create(Error.prototype);
ErrorCollection.prototype.constructor = ErrorCollection;
ErrorCollection.prototype.push = function (e) {
    return this.errors.push(e);
}

// ...

var i, ec = new ErrorCollection();
for (i = 0; i < 10; ++i) {
    try {
        throw new Error('Error ' + i);
    } catch (e) {
        ec.push(e);
    }
}
// do something with ec, e.g.
if (ec.errors.length) {
    console.log(ec, ec.errors);
    throw ec;
}

An example of stopping on the first error then validity checking the remainder

var i, a = [];
for (i = 0; i < arguments.length; ++i) {
    try { // assume everything will work
        this.example(arguments[i]);
    } catch (e) { // our assumption was wrong
        a.push({arg: i, val: arguments[i]});
        for (++i; i < arguments.length; ++i) { // loop from where we left off
            if (!this.valid_arg(arguments[i])) { // some costly test
                a.push({arg: i, val: arguments[i]});
            }
        }
        throw a; // throw the list of bad args up a level
    }
}

If the validity test will be fast/isn't costly then you may consider doing it in advance of your main loop instead of waiting for the first error, as you should then be able to avoid try..catch at this level entirely.

Upvotes: 2

Related Questions