出于某种原因,在下面的代码段中,构造函数委托似乎不起作用:
function NotImplementedError() {
Error.apply(this, arguments);
}
NotImplementedError.prototype = new Error();
var nie = new NotImplementedError("some message");
console.log("The message is: '"+nie.message+"'")
运行该命令得到的消息是:"。有什么想法,为什么,或者是否有更好的方法来创建一个新的错误子类?是否有一个问题,应用到本机错误构造函数,我不知道?
这部分的标准可以解释为什么错误。Apply调用不会初始化对象:
15.11.1错误构造函数作为函数调用
当Error作为函数而不是构造函数调用时,它会创建和
初始化一个新的Error对象。因此函数调用Error(…)是
等价于对象创建表达式new Error(…
相同的参数。
在这种情况下,Error函数可能确定它没有作为构造函数被调用,因此它返回一个新的Error实例,而不是初始化this对象。
用下面的代码进行测试似乎证明了这就是实际发生的情况:
function NotImplementedError() {
var returned = Error.apply(this, arguments);
console.log("returned.message = '" + returned.message + "'");
console.log("this.message = '" + this.message + "'");
}
NotImplementedError.prototype = new Error();
var nie = new NotImplementedError("some message");
运行此命令时输出如下:
returned.message = 'some message'
this.message = ''
这是我的实现:
class HttpError extends Error {
constructor(message, code = null, status = null, stack = null, name = null) {
super();
this.message = message;
this.status = 500;
this.name = name || this.constructor.name;
this.code = code || `E_${this.name.toUpperCase()}`;
this.stack = stack || null;
}
static fromObject(error) {
if (error instanceof HttpError) {
return error;
}
else {
const { message, code, status, stack } = error;
return new ServerError(message, code, status, stack, error.constructor.name);
}
}
expose() {
if (this instanceof ClientError) {
return { ...this };
}
else {
return {
name: this.name,
code: this.code,
status: this.status,
}
}
}
}
class ServerError extends HttpError {}
class ClientError extends HttpError { }
class IncorrectCredentials extends ClientError {
constructor(...args) {
super(...args);
this.status = 400;
}
}
class ResourceNotFound extends ClientError {
constructor(...args) {
super(...args);
this.status = 404;
}
}
示例用法#1:
app.use((req, res, next) => {
try {
invalidFunction();
}
catch (err) {
const error = HttpError.fromObject(err);
return res.status(error.status).send(error.expose());
}
});
示例用法#2:
router.post('/api/auth', async (req, res) => {
try {
const isLogged = await User.logIn(req.body.username, req.body.password);
if (!isLogged) {
throw new IncorrectCredentials('Incorrect username or password');
}
else {
return res.status(200).send({
token,
});
}
}
catch (err) {
const error = HttpError.fromObject(err);
return res.status(error.status).send(error.expose());
}
});
上面的很多方法都不起作用。
最后一个是一个实际的错误。如果您使用字符串,它看起来很好,但它不会提供堆栈跟踪。如果你抛出错误,你不能有“Uncaught BadError: bad”,所以你必须删除自定义错误(遗憾的是)。如果你抛出一个对象,它看起来有点偏离,最后一个只是一个平均错误。
此方法创建一个具有自定义名称的错误,同时保留堆栈跟踪:
var errProto = Object.create(Error.prototype, {
constructor: {
value: Error,
enumerable: false,
writable: true,
configurable: true
}
})
var isFirefox = !!window.InstallTrigger
// Hide stack for Firefox only, as stacks can cause problems with high "frame" counts.
function createError(name, message, hideStack) {
if (message == null) {
message = ""
}
var customError = Error(message)
customError.name = name
Object.setPrototypeOf(customError, errProto)
if (isFirefox && hideStack) {
customError.stack = ""
} else if (isFirefox) {
var stack = customError.stack
var newline = stack.indexOf("\n") + 1
stack = stack.slice(newline)
customError.stack = stack
var split = stack.split(":")
if (split.length > 4) {
var a = split[3]
var b = split[4]
var t = b.slice(0, b.indexOf("\n"))
customError.lineNumber = Number(a)
customError.columnNumber = Number(t)
}
} else {
var stack = customError.stack
var split = stack.split("\n")
var secondPart = split.slice(2).join("\n")
stack = split[0] + "\n" + secondPart
customError.stack = stack
var split = secondPart.split(":")
var a = split[2]
var b = split[3]
}
throw customError
}
var frame = 0
function aFunction() {
if (++frame === 100) {
createError("LazyError", "function getting lazy", false, true)
} else {
requestAnimationFrame(aFunction)
}
}
setTimeout(aFunction, Math.random() * 500)
* {
font-family: Verdana;
}
Check your inspector!
class NotImplementedError extends Error {
constructor(message) {
super(message);
this.message = message;
}
}
NotImplementedError.prototype.name = 'NotImplementedError';
module.exports = NotImplementedError;
and
try {
var e = new NotImplementedError("NotImplementedError message");
throw e;
} catch (ex1) {
console.log(ex1.stack);
console.log("ex1 instanceof NotImplementedError = " + (ex1 instanceof NotImplementedError));
console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
console.log("ex1.name = " + ex1.name);
console.log("ex1.message = " + ex1.message);
}
它只是这个答案的一个类表示。
输出
NotImplementedError: NotImplementedError message
...stacktrace
ex1 instanceof NotImplementedError = true
ex1 instanceof Error = true
ex1.name = NotImplementedError
ex1.message = NotImplementedError message