如何在switch语句中使用instanceof

ale*_*tes 47 javascript error-handling ecmascript-6

我使用自定义错误(es6-error)允许我根据他们的类处理错误,如下所示:

import { DatabaseEntryNotFoundError, NotAllowedError } from 'customError';

function fooRoute(req, res) {
  doSomethingAsync()
    .then(() => {
      // on resolve / success
      return res.send(200);
    })
    .catch((error) => {
      // on reject / failure
      if (error instanceof DatabaseEntryNotFoundError) {
        return res.send(404);
      } else if (error instanceof NotAllowedError) {
        return res.send(400);
      }
      log('Failed to do something async with an unspecified error: ', error);
      return res.send(500);
    };
}
Run Code Online (Sandbox Code Playgroud)

现在我宁愿为这种类型的流使用开关,导致类似于:

import { DatabaseEntryNotFoundError, NotAllowedError } from 'customError';

function fooRoute(req, res) {
  doSomethingAsync()
    .then(() => {
      // on resolve / success
      return res.send(200);
    })
    .catch((error) => {
      // on reject / failure
      switch (error instanceof) {
        case NotAllowedError:
          return res.send(400);
        case DatabaseEntryNotFoundError:
          return res.send(404);
        default:
          log('Failed to do something async with an unspecified error: ', error);
          return res.send(500);
      }
    });
}
Run Code Online (Sandbox Code Playgroud)

然而,instanceof并不像那样工作.所以后者失败了.

有没有办法在switch语句中检查其类的实例?

Dmi*_*tin 84

一个好的选择是使用对象的constructor 属性:

// on reject / failure
switch (error.constructor) {
    case NotAllowedError:
        return res.send(400);
    case DatabaseEntryNotFoundError:
        return res.send(404);
    default:
        log('Failed to do something async with an unspecified error: ', error);
        return res.send(500);
}
Run Code Online (Sandbox Code Playgroud)

请注意,constructor必须与创建对象的内容完全匹配(假设error是实例,NotAllowedError并且NotAllowedError是其子类Error):

  • error.constructor === NotAllowedErrortrue
  • error.constructor === Errorfalse

这有所不同instanceof,它也可以匹配超类:

  • error instanceof NotAllowedErrortrue
  • error instanceof Errortrue

查看这篇关于constructor财产的有趣帖子.

  • 提醒一句:如果你使用Babel进行转换,你可能会发现上面的switch语句总是遇到默认情况.Babel不允许你在不使用[babel-plugin-transform-b​​uiltin-extend]的情况下继承类似错误的内置类型(https://github.com/loganfsmyth/babel-plugin-transform-b​​uiltin-extend) (5认同)
  • 我比我自己的答案更喜欢这个。这样我就不必检查字符串,但可以检查实际对象。但是,我不确定从技术角度来看哪个更明智。 (3认同)

ya_*_*mon 14

解决方法,以避免if-else。在这里找到

switch (true) {
    case error instanceof NotAllowedError: 
        return res.send(400);

    case error instanceof DatabaseEntryNotFoundError: 
        return res.send(404);

    default:
        log('Failed to do something async with an unspecified error: ', error);
        return res.send(500);
}
Run Code Online (Sandbox Code Playgroud)

  • 天才的想法!交换条件及情况。 (4认同)
  • Typescript 目前无法将其识别为类型保护:https://github.com/microsoft/TypeScript/issues/37178 (3认同)
  • 这应该是答案,因为它与JS的所有口味“向后兼容”。使用error.constructor不适用于所有浏览器和Babel版本 (2认同)
  • 这比 if else 好在哪里?我以为重点不是重复“错误”? (2认同)