在开发库时,我们应该抛出错误/异常吗?

时间:2013-02-07 15:57:01

标签: javascript debugging error-handling shared-libraries

我正在开发一个供其他人使用的pub / sub Mediator库,我不知道如何处理错误。

以下是一段代码示例:

/**
 *
 * @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});
}

此方法是库的一部分。它的API需要一个通道名称和一个有效的回调(函数名,lambda或回调)。

如果channel参数不是字符串,则库很容易停止。如果传递了无效的上下文,则假定窗口。这两个参数中的错误都很容易调试。

但是,如果传递了无效的回调,它会传播错误,直到触发事件(进行频道发布)。在pub / sub系统中,如果事件很少被触发,这可能会成为调试的噩梦。


所以我的问题是......

在这个特定场景中,考虑到我正在为其他人开发javascript库,我应该:

  • 抛出错误以防止进一步的错误传播?
  • 返回false / undefined / -1并且不注册订阅?
  • 正常运行,让它死在某处,将调试留给第三方开发人员

注意: 有a similar question但我的情况有点不同,提供的答案并没有让我的精神放松。

3 个答案:

答案 0 :(得分:1)

我想这个答案更多的是我的观点以及我所遵循的内容。您必须问自己是否应该返回抛出错误并让库的使用者处理错误。如果错误是无法恢复的,则不需要抛出错误(在JS中)。您的库应该能够优雅地回退到替代方案,但如果它不能为某个函数执行此操作,则它应该返回undefined。大多数JS开发人员都会检查未定义,并且在使用库函数时这是一种非常常见的做法。如果无法处理事件,则通常在事件处理程序中返回false。

答案 1 :(得分:1)

应避免使用选项#3。至少return false;。你甚至可以注册无效的回调,期望也没有发布任何事件(因为出了问题)。这种“如果不是一切都出错就无声失败”可能不适用于你的pub / sub示例,但可能会有用例。

选项#2听起来不错。它以某种方式使callback参数显式可选,这可能是您的库的一个功能 - 如果用户不确定自己是否有理由订阅,他可以省略该测试,无论如何你都这样做。您可以将其与调试版本中的console.warn()消息结合使用。

如果出现意外情况,应选择选项#1。它允许您使用描述性自定义错误消息失败。如果回调是一个truthy对象,但不可调用,或者channel参数是布尔值或其他东西,这可能是这种情况 - 取决于你的接口设计是多么封闭/你提供多少重载(在你的情况下,你可以接受字符串到被称为回调或通道字符串数组,例如)。

答案 2 :(得分:0)

错误和异常应该完全停止执行并通知调用者。 “抛出错误以防止进一步的错误传播?”如果在这种情况下不应该执行您的代码,则完全是编写选择。

不过,如果您希望传递错误,您可以返回一些特殊值并在文档中对其进行描述。默认值被开发人员广泛使用,这并不直观,但大多数情况下都有效:

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

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