扩展错误没有消息或堆栈跟踪 [英] Extended Errors do not have message or stack trace

查看:114
本文介绍了扩展错误没有消息或堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过BabelJS运行此代码片段时:

When running this snippet through BabelJS:

class FooError extends Error {
  constructor(message) {
    super(message);
  }
}

let error = new FooError('foo');
console.log(error, error.message, error.stack);

它输出

{}

这不是我期望的。运行

error = new Error('foo');
console.log(error, error.message, error.stack);

生成

{} foo Error: foo
    at eval (eval at <anonymous> (https://babeljs.io/scripts/repl.js?t=2015-05-21T16:46:33+00:00:263:11), <anonymous>:24:9)
    at REPL.evaluate (https://babeljs.io/scripts/repl.js?t=2015-05-21T16:46:33+00:00:263:36)
    at REPL.compile (https://babeljs.io/scripts/repl.js?t=2015-05-21T16:46:33+00:00:210:12)
    at Array.onSourceChange (https://babeljs.io/scripts/repl.js?t=2015-05-21T16:46:33+00:00:288:12)
    at u (https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js:28:185)

这是我从扩展错误中我想要的。

which is exactly what I would like from the extended error.

我的目标是扩展错误转换成各种子类,并在蓝鸟的 catch 匹配中使用它们。

My goal is to extend Error into a variety of subclasses and use them in bluebird's catch matching. So far, that is failing miserably.

为什么子类不显示消息或堆栈跟踪?

Why is the subclass not showing a message or stack trace?

编辑使用Chrome的内置子类化(感谢@coder)完美的工作。这不是特定于Babel,必须如下面的例子(从 @loganfsmyth on Babel's gitter feed )显示:

using Chrome's built-in subclassing (thanks to @coder) works perfectly. This isn't specific to Babel, necessarily, as the following example (from @loganfsmyth on Babel's gitter feed) shows:

// Works
new (function(){
  "use strict";
  return class E extends Error { }
}());
// Doesn't
new (function(){
  "use strict";
  function E(message){
    Error.call(this, message);
  };
  E.prototype = Object.create(Error);
  E.prototype.constructor = E;
  return E;
}());


推荐答案

简而言之,使用babel的transpiled代码扩展只适用于以特定的方式构建的类,并且很多原生的东西似乎并不像这样构建。 Babel的文档警告,扩展许多本地类不能正常工作。

In short, extending using babel's transpiled code only works for classes built in a specific way, and a lot of native stuff doesn't appear to be built like that. Babel's docs warns that extending many native classes doesn't work properly.

您可以创建一个缓冲区类,创建属性手动,如下所示:

You could create a buffer class that creates the properties "manually", something like this:

class ErrorClass extends Error {
  constructor (message) {
    super();

    if (Error.hasOwnProperty('captureStackTrace'))
        Error.captureStackTrace(this, this.constructor);
    else
       Object.defineProperty(this, 'stack', {
          value: (new Error()).stack
      });

    Object.defineProperty(this, 'message', {
      value: message
    });
  }

}

然后再扩展该类: / p>

Then extend that class instead:

class FooError extends ErrorClass {
  constructor(message) {
    super(message);
  }
}






为什么不按预期的方式工作?

如果你看看是什么,你会看到babel首先分配一个超级类的原型的副本到子类,然后当你调用新的SubClass()这个函数调用:

If you look at what is transpiled, you'll see that babel first assigns a copy of the super class' prototype to the sub class, then when you call new SubClass() this function is called:

_get(Object.getPrototypeOf(FooError.prototype), "constructor", this).call(this, message)

其中_get是一个辅助函数注入到脚本中:

Where _get is a helper function injected into the script:

(function get(object, property, receiver) {
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent === null) {
      return undefined;
    } else {
      return get(parent, property, receiver);
    }
  } else if ("value" in desc) {
    return desc.value;
  } else {
    var getter = desc.get;

    if (getter === undefined) {
      return undefined;
    }

    return getter.call(receiver);
  }
});

它会像找到构造函数属性子类'prototype'的原型的描述符,并尝试将新的子类实例作为上下文调用其上下文(如果存在)或返回其值( if(valuein desc) ),在这种情况下是Error构造函数本身。它不会从超级调用中向这个分配任何东西,所以当新对象具有正确的原型时,没有按照你的期望构建它。基本上,超级调用对新构造的对象没有任何作用,只需创建一个新的错误,它不分配给任何东西。

it does something like finds the constructor property descriptor of the sub class' prototype's prototype and tried to call its getter with the new subclass instance as context if it exists or return its value (if ("value" in desc)), in this case the Error constructor itself. It doesn't assign anything to this from the super call so while the new object has the right prototype, it didn't get constructed the way you expect. Basically the super call does nothing to the newly constructed object, just creates a new Error which isn't assigned to anything.

如果我们使用上面定义的 ErrorClass ,它将遵循Babel所预期的类结构。

If we use the ErrorClass defined above, it does adhere to the class structure as expected by Babel.

这篇关于扩展错误没有消息或堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆