背景:
我有一个 npm 模块,其中有常见的错误处理代码,包括自定义错误:
function CustomError () { /* ... */ }
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.constructor = CustomError;
module.exports = CustomError;
我还有一些其他模块(我们称它们为'模块-a' and '模块-b')这两者都依赖于错误处理模块。
我还有一些使用 Bluebirds“过滤捕获”功能的代码:
doSomething
.catch(CustomError, () => { /* ... */ });
问题:
经过一些调试后,我发现(事后看来很明显)在'模块-a'不是由创建的错误实例'模块-b'。这是因为两个模块都有自己的 JS 文件副本,其中包含CustomError
构造函数,两者都是独立运行的。
我宁愿不必诉诸我当前的解决方案,基本上是:
CustomError.isCustomError = e => e.constructor.toString() === CustomError.toString();
进而:
doSomething
.then(CustomError.isCustomError, () => { /* ... */ });
这显然是脆弱的,如果版本不同步就会崩溃。
So...
有什么方法可以确保'模块-a' and '模块-b'两者都使用相同的构造函数实例?或者另一种不太脆弱的解决方案。
这实际上也是浏览器中的一个问题,当你有一个 iframe 时,它会获取自己的副本,例如 Array 构造函数(使instanceof
无用)。
自定义构造函数的解决方案是鸭子类型。以下是一些可能的解决方案,各有利弊。
检查构造函数名称。优点:简单,支持良好。缺点:最好选择一个相当独特的名称,以避免误报并忘记对其进行子分类。
检查对象的属性(例如,同时具有“foo”和“bar”,并且“foo”是一个函数)。优点:基本上是万无一失的。缺点:脆弱:如果您重构自定义错误类,此检查可能会随机中断,相对昂贵。
(推荐)添加属性/方法。这就是许多库(例如,moment.js)处理此问题的方式。
代码示例:
CustomError.prototype._isCustomError = true;
var isCustomError = function isCustomError(obj) {
return obj instanceof CustomError || Boolean(obj._isCustomError);
};
module.exports = {
CustomError,
isCustomError
};
这或多或少正是矩检测给定对象是否为矩对象的方式。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)