【问题标题】:Wrap all of your class in try/catch javascript?用 try/catch javascript 包装你的所有课程?
【发布时间】:2018-02-08 23:50:58
【问题描述】:

如何用如下方法实现一个类?

class ExistingClass {
     function func1() {} // might throw error
     function func2() {} // might throw error
     get try() {
        // Some magic here
        return this; // we need to return this to chain the calls, right? 
     }
}

可以这样称呼

obj.func1() //might throw an error
obj.try.func1() // execute func1 in a try/catch

基本上我想要类似 mochajs 的东西:expect(..).to.not.equal()

更新: 接受的答案应该有效,以下是它的更新版本,支持async 函数

get try() {
    return new Proxy(this, {

        // Intercept method getter
        get: function(target, name) {
            if (typeof target[name] === 'function') {
                if (target[name][Symbol.toStringTag] === 'AsyncFunction') {
                    return async function() {
                        try {
                           await target[name].apply(target, arguments);
                        }
                        catch (e) {}
                    }
                } else {
                    return function() {
                        try {
                            return target[name].apply(target, arguments)
                        }
                        catch (e) {}
                    }
                }
            }
            return target[name];
        }
    });
}

【问题讨论】:

  • 你需要能够调用像obj.try.func1()这样的函数吗?你能用这样的东西吗:obj.try("func1")
  • get try { ... 真的吗?这行得通吗?
  • 我的两分钱:如果我看到代码或 cmets 沿线“吞下错误”,我会以另一种方式运行。只是说。
  • 你应该纠正错误,而不是吞下它们。
  • 我看到 mochajs 他们有类似的东西。 expect(val).not.equal()。我会做这样的事情。它使代码更易于阅读。当然,我们不应该接受错误,有一种情况是我们只想“尝试”而error 并没有那么重要。无论如何,我只是想知道是否有可能做这样的事情。不过,我从不说这是一个好代码。

标签: javascript method-chaining


【解决方案1】:

elclanrs's solution的简化版

class A {
  method() {
    throw 'Error';
  }

  get try() {
    return new Proxy(this, {
      // Intercept method getter
      get(target, name) {
        if (typeof target[name] === 'function') {
          return function () {
              try {
                  return target[name].apply(target, arguments)
              } catch (e) {}
          }
        }
        return target[name];
      }
    });
  }
}

const a = new A;

a.try.method(); // no error

a.method(); // throws error

【讨论】:

  • 这是迄今为止最好的解决方案。谢谢。
【解决方案2】:

您可以在最新的浏览器中使用代理来做到这一点:

class A {
  method() {
    throw 'Error';
  }

  get try() {
    return new Proxy(this, {
      // Intercept method getter
      get(target, name) {
        if (typeof target[name] === 'function') {
          return new Proxy(target[name], {
            // Intercept method call
            apply(target, self, args) {
              try {
                return target.apply(self, args);
              } catch(e) {
                // swallow error
              }
            }
          })
        }
        return target[name];
      }
    });
  }
}

const a = new A;

a.try.method(); // no error

a.method(); // throws error

【讨论】:

  • 不需要双重代理。代理的 getter 可以只返回一个在 try catch 中调用原始函数的函数。
  • @BryanChen 我真的很想看看你的解决方案吗?
  • @BryanChen,当然,这也是一种可能的解决方案,而且代理的性能可能更差。
  • @SkinnyPete 提供的解决方案中有一个问题是,如果我们在方法中引用this,那么在try 之后将是undefined。 @elclanrs 的回答实际上保持了 this 参考完整
  • @jAckOdE:啊,是的,我不应该把apply()放在第一位。 return targ[prop](...args)
【解决方案3】:

对于不支持Proxiespre-ES6 浏览器,如果我需要这样的功能,我会这样做:

/* A constructor created the old-fashioned way. */
function ExistingClass () {
  /* The object that will be assigned to this.try. */
  var shadowObj = {};
  
  /* The function that throws an error (calls illegal constructor). */
  this.func1 = function () {
    return new Element();
  };
  
  /* Iterate over every property of the context. */
  for (var func in this) {
    /* Check whether the property is a function. */
    if (this[func] && this[func].constructor == Function) {
      /* Create a shadow function of the context's method. */
      shadowObj[func] = function () {
        try { return this[func]() }
        catch (e) { console.log("Error caught: " + e.message) }
      }.bind(this);
    }
  }
  
  /* Assign the shadow object to this.try. */
  this.try = shadowObj;
}

/* Example. */
var cls = new ExistingClass;
cls.try.func1();
cls.func1();

【讨论】:

  • 有兴趣在这里看到另一种方法。
猜你喜欢
  • 2016-03-24
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 2015-09-15
  • 2020-03-13
  • 2014-12-04
  • 1970-01-01
  • 2018-08-23
相关资源
最近更新 更多