Подтвердить что ты не робот

Как использовать instanceof в инструкции switch

Я использую пользовательские ошибки (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);
    };
}

Теперь я бы предпочел использовать переключатель для этого типа потока, в результате чего-то вроде:

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);
      }
    });
}

instanceof не работает. Таким образом, последний терпит неудачу.

Есть ли способ проверить экземпляр для его класса в инструкции switch?

4b9b3361

Ответ 1

Хорошим вариантом является использование свойства 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);
}

Обратите внимание, что constructor должен точно совпадать с тем, что был создан объект (предположим, что error является экземпляром NotAllowedError и NotAllowedError является подклассом error):

  • error.constructor === NotAllowedError true
  • error.constructor === Error false

Это отличается от instanceof, что может соответствовать супер классу:

  • error instanceof NotAllowedError true
  • error instanceof Error true

Отметьте этот интересный пост о свойстве constructor.

Ответ 2

Альтернативой этому случаю переключения является наличие поля состояния в конструкторе ошибок.

Например, создайте свою ошибку следующим образом:

class NotAllowedError extends Error {
    constructor(message, status) {
        super(message);
        this.message = message;
        this.status = 403; // Forbidden error code
    }
}

Обработайте вашу ошибку следующим образом:

.catch((error) => {
  res.send(error.status);
});

Ответ 3

Обходной путь, чтобы избежать 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);
}