Throw error javascript new error

Error objects are thrown when runtime errors occur. The Error object can also be used as a base object for user-defined exceptions. See below for standard built-in error types.

Error objects are thrown when runtime errors occur. The Error object can also be used as a base object for user-defined exceptions. See below for standard built-in error types.

Description

Runtime errors result in new Error objects being created and thrown.

Error is a serializable object, so it can be cloned with structuredClone() or copied between Workers using postMessage().

Error types

Besides the generic Error constructor, there are other core error constructors in JavaScript. For client-side exceptions, see Exception handling statements.

EvalError

Creates an instance representing an error that occurs regarding the global function eval().

RangeError

Creates an instance representing an error that occurs when a numeric variable or parameter is outside its valid range.

ReferenceError

Creates an instance representing an error that occurs when de-referencing an invalid reference.

SyntaxError

Creates an instance representing a syntax error.

TypeError

Creates an instance representing an error that occurs when a variable or parameter is not of a valid type.

URIError

Creates an instance representing an error that occurs when encodeURI() or decodeURI() are passed invalid parameters.

AggregateError

Creates an instance representing several errors wrapped in a single error when multiple errors need to be reported by an operation, for example by Promise.any().

InternalError
Non-standard

Creates an instance representing an error that occurs when an internal error in the JavaScript engine is thrown. E.g. «too much recursion».

Constructor

Error()

Creates a new Error object.

Static methods

Error.captureStackTrace()
Non-standard

A non-standard V8 function that creates the stack property on an Error instance.

Error.stackTraceLimit
Non-standard

A non-standard V8 numerical property that limits how many stack frames to include in an error stacktrace.

Error.prepareStackTrace()
Non-standard
Optional

A non-standard V8 function that, if provided by usercode, is called by the V8 JavaScript engine for thrown exceptions, allowing the user to provide custom formatting for stacktraces.

Instance properties

Error.prototype.message

Error message. For user-created Error objects, this is the string provided as the constructor’s first argument.

Error.prototype.name

Error name. This is determined by the constructor function.

Error.prototype.cause

Error cause indicating the reason why the current error is thrown — usually another caught error. For user-created Error objects, this is the value provided as the cause property of the constructor’s second argument.

Error.prototype.fileName
Non-standard

A non-standard Mozilla property for the path to the file that raised this error.

Error.prototype.lineNumber
Non-standard

A non-standard Mozilla property for the line number in the file that raised this error.

Error.prototype.columnNumber
Non-standard

A non-standard Mozilla property for the column number in the line that raised this error.

Error.prototype.stack
Non-standard

A non-standard property for a stack trace.

Instance methods

Error.prototype.toString()

Returns a string representing the specified object. Overrides the Object.prototype.toString() method.

Examples

Throwing a generic error

Usually you create an Error object with the intention of raising it using the throw keyword.
You can handle the error using the try...catch construct:

try {
  throw new Error("Whoops!");
} catch (e) {
  console.error(`${e.name}: ${e.message}`);
}

Handling a specific error type

You can choose to handle only specific error types by testing the error type with the error’s constructor property or, if you’re writing for modern JavaScript engines, instanceof keyword:

try {
  foo.bar();
} catch (e) {
  if (e instanceof EvalError) {
    console.error(`${e.name}: ${e.message}`);
  } else if (e instanceof RangeError) {
    console.error(`${e.name}: ${e.message}`);
  }
  // etc.
  else {
    // If none of our cases matched leave the Error unhandled
    throw e;
  }
}

Differentiate between similar errors

Sometimes a block of code can fail for reasons that require different handling, but which throw very similar errors (i.e. with the same type and message).

If you don’t have control over the original errors that are thrown, one option is to catch them and throw new Error objects that have more specific messages.
The original error should be passed to the new Error in the constructor’s options parameter as its cause property. This ensures that the original error and stack trace are available to higher-level try/catch blocks.

The example below shows this for two methods that would otherwise fail with similar errors (doFailSomeWay() and doFailAnotherWay()):

function doWork() {
  try {
    doFailSomeWay();
  } catch (err) {
    throw new Error("Failed in some way", { cause: err });
  }
  try {
    doFailAnotherWay();
  } catch (err) {
    throw new Error("Failed in another way", { cause: err });
  }
}

try {
  doWork();
} catch (err) {
  switch (err.message) {
    case "Failed in some way":
      handleFailSomeWay(err.cause);
      break;
    case "Failed in another way":
      handleFailAnotherWay(err.cause);
      break;
  }
}

Note: If you are making a library, you should prefer to use error cause to discriminate between different errors emitted — rather than asking your consumers to parse the error message. See the error cause page for an example.

Custom error types can also use the cause property, provided the subclasses’ constructor passes the options parameter when calling super(). The Error() base class constructor will read options.cause and define the cause property on the new error instance.

class MyError extends Error {
  constructor(message, options) {
    // Need to pass `options` as the second parameter to install the "cause" property.
    super(message, options);
  }
}

console.log(new MyError("test", { cause: new Error("cause") }).cause);
// Error: cause

Custom error types

You might want to define your own error types deriving from Error to be able to throw new MyError() and use instanceof MyError to check the kind of error in the exception handler. This results in cleaner and more consistent error handling code.

See «What’s a good way to extend Error in JavaScript?» on StackOverflow for an in-depth discussion.

Note: Some browsers include the CustomError constructor in the stack trace when using ES2015 classes.

class CustomError extends Error {
  constructor(foo = "bar", ...params) {
    // Pass remaining arguments (including vendor specific ones) to parent constructor
    super(...params);

    // Maintains proper stack trace for where our error was thrown (only available on V8)
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, CustomError);
    }

    this.name = "CustomError";
    // Custom debugging information
    this.foo = foo;
    this.date = new Date();
  }
}

try {
  throw new CustomError("baz", "bazMessage");
} catch (e) {
  console.error(e.name); // CustomError
  console.error(e.foo); // baz
  console.error(e.message); // bazMessage
  console.error(e.stack); // stacktrace
}

Specifications

Specification
ECMAScript Language Specification
# sec-error-objects

Browser compatibility

BCD tables only load in the browser

See also

  • A polyfill of Error with modern behavior like support cause is available in core-js
  • throw
  • try...catch
  • The V8 documentation for Error.captureStackTrace(), Error.stackTraceLimit, and Error.prepareStackTrace().

TLDR

throw new Error('problem') captures a number of properties of the place where the error happened.

throw 'problem' does not

new Error('message') captures the execution stack + others

Using an Error object allows you to capture the execution stack at the point where you throw the error. So when the error gets passed up the error handling tree, so does this stack snapshot.

So inserting throw "test error" somewhere in my codebase results in:

enter image description here

Whereas throw new Error('test error') results in:

enter image description here

You can see that the native Error object captures the stack at the point I throw the error and makes it available to whatever captures the error. That makes it easier for me to trace the problem when I’m debugging it.

In addition to that it also captures properties such as fileName, lineNumber and columnNumber.

If you use the stack trace it’s there for exception trackers to log for you

In this case the stack is being printed into the browser console but if you’re using Javascript error logging tools like Appsignal or Bugsnag then that stack will also be available in them too. If you inspect the error object you can access the stack snapshot directly:

err = new Error('test')
err.stack

enter image description here

The heuristic I use for deciding which format to use

When I don’t plan to catch the exception I use new Error('problem')

When I’m throwing an error because something unexpected or out-of-bounds has happened in the application, let’s say the local datastore is corrupted, I might be in a situation where I don’t want to handle it, but I do want to flag it. In this case I’ll use the Error object so I have that stack snapshot.

By using throw new Error('Datastore is corrupted') it’s easier to trace my way back to what’s happened.

When I plan to catch the exception I use throw 'problem'

Edit — on re-reading this I think the next part needs some caution. It’s generally a good idea to be very specific about which error you choose to catch otherwise you can end up catching things that you really wanted to bubble all the way up. In general it’s probably better to create a specific error type and catch that specific error (or message string). This allows errors you didn’t anticipate to bubble up to the surface.»

If the error is an expected error that I plan to catch and handle then I’m not going to get much use out of the stack snapshot.

So, let’s say I use an http service and it returns a 500 HTTP code. I may treat this as an error which I throw "responseCode=500" and then subsequently catch and handle.

В предыдущих уроках мы с вами изучили два
места, в которых JavaScript выбрасывает исключение
в случае каких-то проблем.

В вашем проекте, однако, могут быть и другие
ситуации, которые для вас являются исключительными,
а для JavaScript — нет. В таком случае мы
можете создавать и выбрасывать свои, пользовательские
исключения.

Давайте разберем синтаксис, необходимый для
этого. Для начала исключение нужно создать
с помощью команды new Error, параметром
передав текст исключения:

new Error('текст исключения');

Затем это исключение нужно выбросить с помощью
команды throw:

throw new Error('текст исключения');

Выбрасывание исключение заставляет JavaScript
считать, что случилась исключительная ситуация.
Это значит, что такое исключение можно отловить
с помощью конструкции try-catch и
обработать нужным образом.

Давайте посмотрим на примере, как этим пользоваться.
Пусть у нас есть функция, которая делит одно
число на другое:

function div(a, b) {
return a / b;
}

Давайте будем считать, что деление на ноль
запрещено и при попытке сделать это должна
возникать исключительная ситуация. Для этого
будем проверять в функции, нет ли попытки
делить на 0. Если нет — будем делить,
а если нет — будем бросать исключение:

function div(a, b) {
if (b !== 0) {
return a / b;
} else {
throw new Error('ошибка деления на ноль');
}
}

Давайте для начала просто попробуем поделить
на 0, не перехватывая исключение:

alert( div(3, 0) );

В этом случае выполнение скрипта прервется
и в консоли появится ошибка с текстом 'ошибка
деления на ноль'
(проверьте). Давайте
теперь будем перехватывать нашу ошибку и
как-то ее обрабатывать:

try {
alert( div(3, 0) );
} catch (error) {
alert('вы пытаетесь делить на 0, что запрещено');
}

В JavaScript попытка извлечь корень из отрицательного
числа не приводит к выбрасыванию исключения:

let result = Math.sqrt(-1);
console.log(result); // выведет NaN

Напишите свою функцию, которая будет извлекать
корень из числа и при этом выбрасывать исключение,
если корень извлекается из отрицательного числа.

Типы исключений

Давайте выбросим свое исключение и посмотрим,
как будет вести себя объект с ошибкой в этом
случае:

try {
throw new Error('текст исключения');
} catch (error) {
console.log(error.name); // 'Error'
console.log(error.message); // 'текст исключения'
}

Как вы видите, тип нашего исключения — 'Error'.
Такой же тип будет у любых исключений, выброшенных
подобным образом. Это, однако, не всегда
будет удобно, так как, если у нас могут быть
несколько исключений, мы не сможем их отличить
друг от друга.

В JavaScript предусмотрено решение этой проблемы:
можно выбрасывать исключения не только типа
Error, но и любого встроенного в JavaScript
типа ошибки, например, TypeError,
SyntaxError, RangeError.

Давайте для примера выбросим исключение типа
SyntaxError:

try {
throw new SyntaxError('текст исключения');
} catch (error) {
console.log(error.name); // 'SyntaxError'
console.log(error.message); // 'текст исключения'
}

Выбросите исключение с типом TypeError.

Выбросите исключение с типом SyntaxError
и RangeError. Поймайте эти исключения
с помощью одного блока try. В блоке catch
выведите разные сообщения об ошибке для исключений
разных типов.

Свои типы исключений

Количество встроенных в JavaScript исключений
не такое большое и они чаще всего не могут
удовлетворить все наши потребности в разных
типах исключений. Поэтому в JavaScript встроена
возможность создавать исключения со своим типом.

Существуют разные способы сделать это. Самый
простой — в throw передать объект
с ключами name и message:

try {
throw {name: 'MyError', message: 'текст исключения'};
} catch (error) {
console.log(error.name); // 'MyError'
console.log(error.message); // 'текст исключения'
}

Выше я мы сделали функцию, выбрасывающую
исключение при делении на ноль:

function div(a, b) {
if (b !== 0) {
return a / b;
} else {
throw new Error('ошибка деления на ноль');
}
}

Переделайте эту функцию так, чтобы она выбрасывала
исключение с каким-нибудь придуманными нами
типом, например, DivisionByZeroError.

Выше вы делали функцию, выбрасывающую исключение
при попытке извлечь корень из отрицательного
числа. Переделайте вашу функцию так, чтобы
она выбрасывала исключение с придуманным
вами типом. Хорошо подумайте над названием
исключения, чтобы это название было удачным.

Пример применения

Пусть при загрузке страницы сервер создает
HTML код, в котором хранится название, цена
и количество купленного продукта:

<div id="product" data-product="яблоко" data-price="1000" data-amount="5"></div>

Давайте сделаем функцию, которая будет принимать
ссылку на элемент с продуктом и находить
полную стоимость товара (цену умножать на
количество):

function getCost(elem) {
return elem.dataset.price * elem.dataset.amount;
}

Найдем стоимость нашего продукта:

let product = document.querySelector('#product');
let cost = getCost(product);

alert(cost);

Предположим теперь следующую ситуацию: из-за
какого-то сбоя на сервере он прислал нам
товар, в котором отсутствует цена или количество
(или оба сразу), например, вот так:

<div id="product" data-product="яблоко" data-price="1000"></div>

Если теперь попробовать посчитать стоимость
товара, то результате на экран выведется
NaN. Согласитесь, не очень информативно.

Получается, нам нужно как-то обезопасится
от того, что будут отсутствовать нужные нам
атрибуты. Это можно сделать двумя путями.
Первый путь — это сказать, что это нормальное
поведение и просто поверять ифами наличие
нужных нам атрибутов:

function getCost(elem) {
if (elem.dataset.price !== undefined && elem.dataset.amount !== undefined) {
return elem.dataset.price * elem.dataset.amount;
} else {
return 0; // вернем что-нибудь, например, 0 или null или false
}
}

Второй вариант — это сказать, что отсутствие
атрибута data-price или data-amount
— исключительная ситуация. В этом случае
мы будем выбрасывать исключение:

function getCost(elem) {
if (elem.dataset.price !== undefined && elem.dataset.amount !== undefined) {
return elem.dataset.price * elem.dataset.amount;
} else {
throw {
name: 'ProductCostError',
message: 'отсутствует цена или количество у продукта'
};
}
}

Какой из двух вариантов здесь уместнее применить
— это выбор программиста. Он может считать
проблему нормальной работой скрипта или исключительной
ситуацией.

Пусть мы решили, что ситуация исключительная.
Тогда код получения стоимости товара будет
выглядеть вот так:

let product = document.querySelector('#product');

try {
let cost = getCost(product);
alert(cost);
} catch (error) {
// как-то реагируем на исключение
}

Переделайте мой код так, чтобы функция getCost
выбрасывала два типа исключений: если отсутствует
цена и если отсутствует количество. Хорошо
подумайте над названиями этих исключений.
В блоке catch выведите разные сообщения об
ошибке для исключений разных типов.

Еще пример применения

Пусть к нам откуда-то из внешнего мира приходит
JSON с продуктом:

let json = '{"product": "яблоко", "price": 1000, "amount": 5}';
let product = JSON.parse(json);
alert(product.price * product.amount);

Вы уже знаете, что метод JSON.parse будет
выбрасывать исключение, если JSON некорректный.
Давайте поймаем это исключение:

try {
let json = '{"product": "яблоко", "price": 1000, "amount": 5}';
let product = JSON.parse(json);
alert(product.price * product.amount);
} catch (error) {
// как-то реагируем на исключение
}

Однако, может быть такое, что сам по себе
JSON корректный, но не содержит нужных нам
полей, например, нет поля с ценой:

let json = '{"product": "яблоко", "amount": 5}'; // нет цены

Давайте скажем, что это тоже исключительная
ситуация и будем в таком случае выбрасывать
свое пользовательское исключение:

try {
let json = '{"product": "яблоко", "amount": 5}';
let product = JSON.parse(json);

if (product.price !== undefined && product.amount !== undefined) {
alert(product.price * product.amount);
} else {
throw {
name: 'ProductCostError',
message: 'отсутствует цена или количество у продукта'
};
}
} catch (error) {
// как-то реагируем на исключение
}

Теперь блок catch будет получать два типа
исключений: либо JSON вообще некорректен,
и тогда будет исключение типа SyntaxError,
либо JSON корректен, но не содержит нужных
нам полей, и тогда будет исключение типа
ProductCostError.

Давайте в блоке catch будем отлавливать эти
типы исключений:

try {
let json = '{"product": "яблоко", "amount": 5}';
let product = JSON.parse(json);

if (product.price !== undefined && product.amount !== undefined) {
alert(product.price * product.amount);
} else {
throw {
name: 'ProductCostError',
message: 'отсутствует цена или количество у продукта'
};
}
} catch (error) {
if (error.name == 'SyntaxError') {
alert('Некорректный JSON продукта');
} else if (error.name == 'ProductCostError') {
alert('У продукта отсутствует цена или количество');
}
}

Пусть к вам приходит JSON вот такого вида:

let json = `[
{
"name": "user1",
"age": 25,
"salary": 1000
},
{
"name": "user2",
"age": 26,
"salary": 2000
},
{
"name": "user3",
"age": 27,
"salary": 3000
}
]`;

Проверьте этот JSON на общую корректность
при разборе, а после разбора проверьте, что
в результате получается массив, а не что-то
другое. Если в результате получается не массив
— выбросите исключение.

Проброс исключений

Рассмотрим блок catch задачи о JSON продукта:

catch (error) {
if (error.name == 'SyntaxError') {
alert('Некорректный JSON продукта');
} else if (error.name == 'ProductCostError') {
alert('У продукта отсутствует цена или количество');
}
}

Как вы видите, мы ловим два запланированных
нами исключения и как-то реагируем на это.
Но что будет, если возникнет непредусмотренное
нами исключение другого типа? В этом случае
оно тоже попадет в блок catch, но
никакой реакции на это не последует, так
как исключение с другим типом просто не попадет
ни в один из наших ифов.

Когда я говорю, что не будет никакой реакции,
то имею ввиду, что реально никакой: даже
не будет вываливания ошибки в консоль. Наш
код просто молча не будет работать.

Поэтому существует следующее правило: ваш
код должен ловить только те исключения, с
которыми знает, как справится. Если исключение
не известное, то его нужно пробросить
дальше с помощью throw. В этом случае
его выше поймает кто-то более осведомленный
либо исключение вывалится ошибкой в консоль.

Давайте поправим наш код:

catch (error) {
if (error.name == 'SyntaxError') {
alert('Некорректный JSON продукта');
} else if (error.name == 'ProductCostError') {
alert('У продукта отсутствует цена или количество');
} else {
throw error; // пробрасываем исключение далее
}
}

Дан следующий код:

try {
let arr = JSON.parse(json);

for (let i = 0; i < arr.length; i++) {
localStorage.setItem(i, arr[i]);
}
} catch (error) {
if (error.name == 'QuotaExceededError') {
alert('закончилось место в хранилище');
}

if (error.name == 'SyntaxError') {
alert('некорректный JSON');
}
}

Что не так с этим кодом? Исправьте его на
более удачный.

Понравилась статья? Поделить с друзьями:
  • Throw er unhandled error event node js
  • Through trial and error перевод
  • Throttling error esme has exceeded allowed message limits
  • Threed32 ocx ошибка
  • Three phase current error value перевод