简体   繁体   中英

When developing a library, should we throw errors/exceptions?

I'm developing a pub/sub Mediator library to be used by others and I don't know how to handle errors.

Here's an example piece of code:

/**
 *
 * @param String channel Channel to subscribe
 * @param String|function callback Function name or callback
 * @param String context Context to bind function to
 * @param Boolean once True to subscribe once
 **/
this.subscribe = function (channel, callback, context, once) {

    if (!_.isObject(context)) {
         context = window;
    }

    if (!_.isFunction(subscription) && !_.isFunction(context[subscription])) {
        throw new Error('Function passed as callback to channel subscription named  ' + channel + ' seems invalid!');
    }

    // Everything ok, add to channels object
    channels[channel].push({fn: subscription, context: context || this, once: once});
}

This method is part of the library. It's API expects a channel name and a valid callback (either the function name, a lambda or a callback).

If the channel argument is not a string, the library readily stop. If an invalid context is passed, window is assumed. Mistakes in both these parameters are easily debugaable.

However, if an invalid callback is passed, it propagates the error until an event is fired (a channel publishing is made). In a pub/sub system this might become a nightmare to debug if, for instance, the event is rarely fired.


So my question is...

In this specific scenario, taking in account that I'm developing a javascript library to others, should I:

  • throw Errors to prevent further error propagation?
  • return false/undefined/-1 and not register the subscription?
  • proceed as normal at let it die somewhere, leaving the debugging to the third party developer

NOTE: There's a similar question but my situation is a bit different and the answers provided didn't put my spirit at ease.

I guess this answer is more of my opinion and what I follow. You have to ask yourself if you should return throw an error and let the consumer, of your library, handle the error. If the error is something that cannot be recovered from, there is no need for you to throw an error (in JS). Your library should be able to fallback gracefully to alternatives but if it cannot do that for a certain function, it should return undefined. Most JS developers do check for undefined and it's a pretty common practice to do so while using library functions. Returning false is usually done in event handlers if an event cannot be handled.

Option #3 should be avoided. At least, return false; . You even might register the invalid callback, expecting that no events are published as well (since something went wrong). This "silent fail if not everything went wrong" might not really be applicable to your pub/sub example, yet there might be use cases for it.

Option #2 sounds good. It somehow makes the callback parameter explicitly optional, which could be a feature of your library - if the user is not sure himself whether he has a reason to subscribe, he can omit that test if you are doing it anyway. You might combine this with a console.warn() message in debugging versions.

Option #1 should be chosen if something really unexpected happened. It allows you to fail with a very descriptive custom Error message. This could be the case if the callback is a truthy object, but not callable, or the channel argument is a boolean or something - depending on how closed your interface design is / how much overloading you provide (in your case you could accept strings to be evaled as callbacks, or arrays of channel strings for example).

Errors and Exceptions are supposed exactly to stop the execution and notify the caller about it. "throw Errors to prevent further error propagation?" is exactly write choice if your code is not supposed to be executed in that case.

Still, if you expect something to be passed wrong, you can return some special value and describe it in the documentation. Default values are widely used by developers, that's not intuitive,but mostly works tho:

/*
* ...
* Returns a Socket if found, otherwise undefined
*/

function FindSocketOrUndefined(): Socket|undefined {
...
return undefined
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM