Ошибка при выполнении js вызова как исправить

Время на прочтение
5 мин

Количество просмотров 397K

JavaScript может быть кошмаром при отладке: некоторые ошибки, которые он выдает, могут быть очень трудны для понимания с первого взгляда, и выдаваемые номера строк также не всегда полезны. Разве не было бы полезно иметь список, глядя на который, можно понять смысл ошибок и как исправить их? Вот он!

Ниже представлен список странных ошибок в JavaScript. Разные браузеры могут выдавать разные сообщения об одинаковых ошибках, поэтому приведено несколько примеров там, где возможно.

Как читать ошибки?

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

Типичная ошибка из Chrome выглядит так:

Uncaught TypeError: undefined is not a function

Структура ошибки следующая:

  1. Uncaught TypeError: эта часть сообщения обычно не особо полезна. Uncaught значит, что ошибка не была перехвачена в catch, а TypeError — это название ошибки.
  2. undefined is not a function: это та самая часть про ошибку. В случае с сообщениями об ошибках, читать их нужно прямо буквально. Например, в этом случае, она значит то, что код попытался использовать значение undefined как функцию.

Другие webkit-браузеры, такие как Safari, выдают ошибки примерно в таком же формате, как и Chrome. Ошибки из Firefox похожи, но не всегда включают в себя первую часть, и последние версии Internet Explorer также выдают более простые ошибки, но в этом случае проще — не всегда значит лучше.

Теперь к самим ошибкам.

Uncaught TypeError: undefined is not a function

Связанные ошибки: number is not a function, object is not a function, string is not a function, Unhandled Error: ‘foo’ is not a function, Function Expected

Возникает при попытке вызова значения как функции, когда значение функцией не является. Например:

var foo = undefined;
foo();

Эта ошибка обычно возникает, если вы пытаетесь вызвать функцию для объекта, но опечатались в названии.

var x = document.getElementByID('foo');

Несуществующие свойства объекта по-умолчанию имеют значение undefined, что приводит к этой ошибке.

Другие вариации, такие как “number is not a function” возникают при попытке вызвать число, как будто оно является функцией.

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

Uncaught ReferenceError: Invalid left-hand side in assignment

Связанные ошибки: Uncaught exception: ReferenceError: Cannot assign to ‘functionCall()’, Uncaught exception: ReferenceError: Cannot assign to ‘this’

Вызвано попыткой присвоить значение тому, чему невозможно присвоить значение.

Наиболее частый пример этой ошибки — это условие в if:

if(doSomething() = 'somevalue')

В этом примере программист случайно использовал один знак равенства вместо двух. Выражение “left-hand side in assignment” относится к левой части знака равенства, а, как можно видеть в данном примере, левая часть содержит что-то, чему нельзя присвоить значение, что и приводит к ошибке.

Как исправить ошибку: убедитесь, что вы не пытаетесь присвоить значение результату функции или ключевому слову this.

Uncaught TypeError: Converting circular structure to JSON

Связанные ошибки: Uncaught exception: TypeError: JSON.stringify: Not an acyclic Object, TypeError: cyclic object value, Circular reference in value argument not supported

Всегда вызвано циклической ссылкой в объекте, которая потом передается в JSON.stringify.

var a = { };
var b = { a: a };
a.b = b;
JSON.stringify(a);

Так как a и b в примере выше имеют ссылки друг на друга, результирующий объект не может быть приведен к JSON.

Как исправить ошибку: удалите циклические ссылки, как в примере выше, из всех объектов, которые вы хотите сконвертировать в JSON.

Unexpected token ;

Связанные ошибки: Expected ), missing ) after argument list

Интерпретатор JavaScript что-то ожидал, но не обнаружил там этого. Обычно вызвано пропущенными фигурными, круглыми или квадратными скобками.

Токен в данной ошибке может быть разным — может быть написано “Unexpected token ]”, “Expected {” или что-то еще.

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

Ошибка с [ ] { } ( ) обычно вызвано несовпадающей парой. Проверьте, все ли ваши скобки имеют закрывающую пару. В этом случае, номер строки обычно указывает на что-то другое, а не на проблемный символ.

Unexpected / связано с регулярными выражениями. Номер строки для данного случая обычно правильный.

Unexpected; обычно вызвано символом; внутри литерала объекта или массива, или списка аргументов вызова функции. Номер строки обычно также будет верным для данного случая.

Uncaught SyntaxError: Unexpected token ILLEGAL

Связанные ошибки: Unterminated String Literal, Invalid Line Terminator

В строковом литерале пропущена закрывающая кавычка.

Как исправить ошибку: убедитесь, что все строки имеют правильные закрывающие кавычки.

Uncaught TypeError: Cannot read property ‘foo’ of null, Uncaught TypeError: Cannot read property ‘foo’ of undefined

Связанные ошибки: TypeError: someVal is null, Unable to get property ‘foo’ of undefined or null reference

Попытка прочитать null или undefined так, как будто это объект. Например:

var someVal = null;
console.log(someVal.foo);

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

Uncaught TypeError: Cannot set property ‘foo’ of null, Uncaught TypeError: Cannot set property ‘foo’ of undefined

Связанные ошибки: TypeError: someVal is undefined, Unable to set property ‘foo’ of undefined or null reference

Попытка записать null или undefined так, как будто это объект. Например:

var someVal = null;
someVal.foo = 1;

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

Uncaught RangeError: Maximum call stack size exceeded

Связанные ошибки: Uncaught exception: RangeError: Maximum recursion depth exceeded, too much recursion, Stack overflow

Обычно вызвано неправильно программной логикой, что приводит к бесконечному вызову рекурсивной функции.

Как исправить ошибку: проверьте рекурсивные функции на ошибки, которые могут вынудить их делать рекурсивные вызовы вечно.

Uncaught URIError: URI malformed

Связанные ошибки: URIError: malformed URI sequence

Вызвано некорректным вызовом decodeURIComponent.

Как исправить ошибку: убедитесь, что вызовы decodeURIComponent на строке ошибки получают корректные входные данные.

XMLHttpRequest cannot load some/url. No ‘Access-Control-Allow-Origin’ header is present on the requested resource

Связанные ошибки: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at some/url

Эта проблема всегда связана с использованием XMLHttpRequest.

Как исправить ошибку: убедитесь в корректности запрашиваемого URL и в том, что он удовлетворяет same-origin policy. Хороший способ найти проблемный код — посмотреть на URL в сообщении ошибки и найти его в своём коде.

InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

Связанные ошибки: InvalidStateError, DOMException code 11

Означает то, что код вызвал функцию, которую нельзя было вызывать в текущем состоянии. Обычно связано c XMLHttpRequest при попытке вызвать на нём функции до его готовности.

var xhr = new XMLHttpRequest();
xhr.setRequestHeader('Some-Header', 'val');

В данном случае вы получите ошибку потому, что функция setRequestHeader может быть вызвана только после вызова xhr.open.

Как исправить ошибку: посмотрите на код в строке, указывающей на ошибку, и убедитесь, что он вызывается в правильный момент или добавляет нужные вызовы до этого (как с xhr.open).

Заключение

JavaScript содержит в себе одни из самых бесполезных ошибок, которые я когда-либо видел, за исключением печально известной Expected T_PAAMAYIM_NEKUDOTAYIM в PHP. Большая ознакомленность с ошибками привносит больше ясности. Современные браузеры тоже помогают, так как больше не выдают абсолютно бесполезные ошибки, как это было раньше.

Какие самые непонятные ошибки вы встречали? Делитесь своими наблюдениями в комментариях.

P.S. Этот перевод можно улучшить, отправив PR здесь.

  • Назад
  • Обзор: Первые шаги
  • Далее

Когда вы создали игру «Угадай номер» в предыдущей статье, вы, возможно, обнаружили, что она не работает. Не бойтесь — эта статья призвана избавить вас от разрыва волос над такими проблемами, предоставив вам несколько простых советов о том, как найти и исправить ошибки в программах JavaScript.

Нужно: базовая компьютерная грамотность, базовое понимание HTML и CSS, понимание того, что такое JavaScript.
Цель получить способность и уверенность в том, чтобы приступить к исправлению простых проблем в вашем собственном коде.

Типы ошибок

Когда вы делаете что-то не так в коде, есть два основных типа ошибок, с которыми вы столкнётесь:

  • Синтаксические ошибки: Это орфографические ошибки в коде, которые фактически заставляют программу вообще не запускаться, или перестать работать на полпути — вам также будут предоставлены некоторые сообщения об ошибках. Обычно они подходят для исправления, если вы знакомы с правильными инструментами и знаете, что означают сообщения об ошибках!
  • Логические ошибки: Это ошибки, когда синтаксис действительно правильный, но код не тот, каким вы его предполагали, что означает, что программа работает успешно, но даёт неверные результаты. Их часто сложнее находить, чем синтаксические ошибки, так как обычно не возникает сообщение об ошибке, которое направляет вас к источнику ошибки.

Ладно, все не так просто — есть и другие отличия, которые вы поймёте, пока будете изучать язык JavaScript глубже. Однако вышеуказанной классификации достаточно на раннем этапе вашей карьеры. Мы рассмотрим оба эти типа в дальнейшем.

Ошибочный пример

Чтобы начать работу, давайте вернёмся к нашей игре с угадыванием чисел — за исключением того, что мы будем изучать версию с некоторыми преднамеренными ошибками. Перейдите в Github и сделайте себе локальную копию number-game-errors.html (см. здесь как это работает).

  1. Чтобы начать работу, откройте локальную копию внутри вашего любимого текстового редактора и вашего браузера.
  2. Попробуйте сыграть в игру — вы заметите, что когда вы нажимаете кнопку «Submit guess», она не работает!

Примечание: Возможно, у вас может быть собственная версия игрового примера, которая не работает, которую вы можете исправить! Мы по-прежнему хотели бы, чтобы вы работали над статьёй с нашей версией, чтобы вы могли изучать методы, которые мы здесь преподаём. Затем вы можете вернуться и попытаться исправить ваш пример.

На этом этапе давайте рассмотрим консоль разработчика, чтобы увидеть, можем ли мы видеть какие-либо синтаксические ошибки, а затем попытаемся их исправить. Вы узнаете, как это сделать, ниже.

Исправление синтаксических ошибок

Раньше в курсе мы заставили вас набрать некоторые простые команды JavaScript в консоль разработчика JavaScript (если вы не можете вспомнить, как открыть это в своём браузере, следуйте предыдущей ссылке, чтобы узнать, как это сделать). Что ещё более полезно, так это то, что консоль предоставляет вам сообщения об ошибках всякий раз, когда существует синтаксическая ошибка внутри JavaScript, которая подаётся в механизм JavaScript браузера. Теперь пойдём на охоту.

  1. Перейдите на вкладку, в которой у вас есть number-game-errors.html, и откройте консоль JavaScript. Вы должны увидеть сообщение об ошибке в следующих строках:
  2. Это довольно простая ошибка для отслеживания, и браузер даёт вам несколько полезных бит информации, которые помогут вам (скриншот выше от Firefox, но другие браузеры предоставляют аналогичную информацию). Слева направо, у нас есть:
    • Красный «x» означает, что это ошибка.
    • Сообщение об ошибке, указывающее, что пошло не так: «TypeError: guessSubmit.addeventListener не является функцией»
    • Ссылка «Узнать больше», которая ссылается на страницу MDN, которая объясняет, что эта ошибка означает в огромных количествах деталей.
    • Имя файла JavaScript, который ссылается на вкладку «Отладчик» консоли разработчика. Если вы перейдёте по этой ссылке, вы увидите точную строку, где подсвечивается ошибка.
    • Номер строки, в которой находится ошибка, и номер символа в этой строке, где первая ошибка. В этом случае у нас есть строка 86, символ номер 3.
  3. Если мы посмотрим на строку 86 в нашем редакторе кода, мы найдём эту строку:
    guessSubmit.addeventListener('click', checkGuess);
    
  4. В сообщении об ошибке говорится, что «guessSubmit.addeventListener не является функцией», поэтому мы, вероятно, где-то ошиблись. Если вы не уверены в правильности написания синтаксиса, часто бывает полезно найти функцию на MDN. Лучший способ сделать это в настоящее время — поиск «mdn имя-функции» в вашей любимой поисковой системе. Вот ссылка, которая поможет сократить вам некоторое время в данном случае: addEventListener().
  5. Итак, глядя на эту страницу, кажется, что ошибка в том, что мы неправильно назвали имя функции! Помните, что JavaScript чувствителен к регистру, поэтому любые незначительные отличия в орфографии или регистре текста могут вызвать ошибку. Изменение этого параметра в addEventListener должно быть исправлено. Сделайте это сейчас.

**Примечание:**См. наш TypeError: «x» не является справочной страницей функций для получения дополнительной информации об этой ошибке.

Синтаксические ошибки: второй раунд

Примечание: console.log() это часто используемая функция отладки, которая выводит значение в консоль. Поэтому она будет выводить значение lowOrHi в консоли, как только мы попытаемся установить его в строке 48.

  1. Сохраните и обновите страницу, и вы увидите, что ошибка исчезла.
  2. Теперь, если вы попробуете ввести значение и нажать кнопку «Submit guess», вы увидите … другую ошибку!
  3. На этот раз сообщается об ошибке: «TypeError: lowOrHi is null», в строке 78.

    Примечание: Null — это специальное значение, которое означает «ничего» или «не значение». Поэтому lowOrHi был объявлен и инициализирован без значения — у него нет типа или значения.

    Примечание: Эта ошибка не появилась, как только страница была загружена, потому что эта ошибка произошла внутри функции (внутри checkGuess() { ... } блока). Об этом вы узнаете более подробно в нашей более поздней статье о функциях, код внутри функций выполняется в отдельной области для кода внешних функций. В этом случае код не был запущен, и ошибка не была брошена до тех пор, пока функция checkGuess() не была запущена строкой 86.

  4. Посмотрите на строку 78, и вы увидите следующий код:
    lowOrHi.textContent = 'Last guess was too high!';
    
  5. Эта строка пытается установить свойство textContent переменной lowOrHi как текстовую строку, но это не работает, поскольку lowOrHi не содержит того, что должна. Давайте посмотрим, почему так происходит — попробуйте найти другие экземпляры lowOrHi в коде. Самый ранний экземпляр, который вы найдёте в JavaScript, находится в строке 48:
    const lowOrHi = document.querySelector('lowOrHi');
    
  6. На этом этапе мы пытаемся заставить переменную содержать ссылку на элемент документа HTML. Давайте проверим, является ли значение null после выполнения этой строки. Добавьте следующий код в строку 49:
  7. Сохраните и обновите, и вы должны увидеть результат работы console.log() в консоли браузера.
    Разумеется, значение lowOrHi на данный момент равно null, поэтому определённо существует проблема в строке 48.
  8. Давайте подумаем о том, что может быть проблемой. Строка 48 использует метод document.querySelector() для получения ссылки на элемент, выбирая его с помощью селектора CSS. Посмотрев далее наш файл, мы можем найти обсуждаемый элемент <p>:
  9. Поэтому нам нужен селектор классов, который начинается с точки (.), но селектор, передаваемый в метод querySelector() в строке 48, не имеет точки. Возможно, это и есть проблема! Попробуйте изменить lowOrHi на .lowOrHi в строке 48.
  10. Повторите попытку сохранения и обновления, и ваш вызов console.log() должен вернуть элемент <p>, который мы хотим. Уф! Ещё одна ошибка исправлена! Вы можете удалить строку с console.log() сейчас, или оставить для дальнейшего применения — выбирайте сами.

Примечание: Загляните на справочную страницу TypeError: «x» is (not) «y», чтобы узнать больше об этой ошибке.

Синтаксические ошибки: третий раунд

  1. Теперь, если вы снова попробуете сыграть в игру, вы должны добиться большего успеха — игра должна играть абсолютно нормально, пока вы не закончите игру, либо угадав нужное число, либо потеряв жизни.
  2. На данном этапе игра снова слетает, и выводится такая же ошибка, как и в начале — «TypeError: resetButton.addeventListener is not a function»! Однако, теперь она происходит из-за строки 94.
  3. Посмотрев на строку 94, легко видеть, что здесь сделана такая же ошибка. Нам просто нужно изменить addeventListener на addEventListener.

Логическая ошибка

На этом этапе игра должна проходить отлично, однако, поиграв несколько раз, вы, несомненно заметите, что случайное число, которое вы должны угадать, всегда 0 или 1. Определённо не совсем так, как мы хотим, чтобы игра была разыграна!

Безусловно, где-то в игре есть логическая ошибка — игра не возвращает ошибку, она просто работает неправильно.

  1. Найдём переменную randomNumber , и строку где в первый раз устанавливали случайное число. Пример, в котором мы храним случайное число, которое должны угадать, на строке 44:
    let randomNumber = Math.floor(Math.random()) + 1;
    

    И на строке 113, где мы генерируем случайное число, каждый раз после окончания игры:

    randomNumber = Math.floor(Math.random()) + 1;
    
  2. Чтобы проверить, действительно ли проблема в этом, давайте обратимся к нашему другу console.log() снова — вставьте её ниже строк с ошибками:
    console.log(randomNumber);
    
  3. Сохраните и обновите, а дальше попробуйте пару раз сыграть — в консоли вы увидите что randomNumber равна 1 в каждой точке, где вы её записали после строк с ошибками.

Работаем через логику

Чтобы исправить это, давайте рассмотрим как работает строка. Первое, мы вызываем Math.random(), который генерирует случайное десятичное число, между 0 и 1, например 0.5675493843.

Дальше, мы передаём результат вызова Math.random() через Math.floor(), который округляет число вниз, до ближайшего целого числа. Затем мы добавляем 1 к данному результату:

Math.floor(Math.random()) + 1;

Округление случайного десятичного числа к меньшему, всегда будет возвращать 0, так что добавление к нему единицы будет возвращать всегда 1. Нам нужно умножить случайное число на 100, прежде чем мы округлим его к меньшему. Следующая строка вернёт нам случайное число между 0 и 99:

Math.floor(Math.random() * 100);

поэтому нам нужно добавить 1, чтоб нам возвращалось случайное число между 1 и 100:

Math.floor(Math.random() * 100) + 1;

А теперь, исправьте обе строки с ошибками, затем сохраните и обновите, игра должна работать так, как мы и планировали!

Другие распространённые ошибки

Существуют и другие распространённые ошибки, которые вы обнаружите в своём коде. В этом разделе показано большинство из них.

SyntaxError: отсутствует ; перед постановкой

Эта ошибка обычно означает что вы упустили точку с запятой в конце одной из ваших строк кода, но иногда ошибка может быть более загадочной. Например, если мы изменим эту строку внутри функции checkGuess() :

var userGuess = Number(guessField.value);

на эту

var userGuess === Number(guessField.value);

Это вызовет данную ошибку, потому что браузер подумает, что вы пытались сделать что-то другое. Вы должны быть уверены, что вы не перепутали оператор присваивания (=), который присваивает значение переменной — с оператором сравнения (===), который строго сравнивает операнды, и возвращает true/false .

В программе всегда говорится, что вы выиграли, независимо от того, что вы ввели

Причиной этому является все то же перепутывание оператора присваивания (=) со строгим сравнением (===). Например, если мы изменим внутри checkGuess() эту строку кода:

if (userGuess === randomNumber) {

на эту

if (userGuess = randomNumber) {

мы всегда будем получать true, заставляя программу сообщать, что игра была выиграна. Будьте осторожны!

SyntaxError: отсутствует ) после списка аргументов

Эта ошибка проста — обычно она означает, что вы пропустили закрывающую скобку с конца вызова функции / метода.

SyntaxError: missing : after property id

Эта ошибка обычно связана с неправильно сформированным объектом JavaScript, но в этом случае нам удалось получить её, изменив

на

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

SyntaxError: missing } after function body

Это легко — обычно это означает, что вы пропустили одну из ваших фигурных скобок из функции или условной структуры. Мы получили эту ошибку, удалив одну из закрывающих фигурных скобок возле нижней части функции checkGuess().

SyntaxError: expected expression, got ‘string‘ or SyntaxError: unterminated string literal

Эти ошибки обычно означает, что вы пропустили открывающую или закрывающую кавычку для строковых значений. В первой ошибки выше, строка будет заменена на неожиданный персонаж (ей) , что браузер нашёл вместо кавычек в начале строки. Вторая ошибка означает , что строка не закончилась кавычки.

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

Резюме

Итак, мы научились основам выяснения ошибок в простых программах JavaScript. Не всегда так просто разобраться, что не так в вашем коде, но, по крайней мере, это сэкономит вам несколько часов сна и позволит вам продвигаться немного быстрее, когда что-либо заработает не так, как ожидалось, в вашем учебном путешествии.

Смотрите также

  • Есть много других типов ошибок, которые не перечислены здесь; мы составляем ссылку , которая объясняет , что они означают подробно — см. ссылку ошибки JavaScript .
  • Если вы столкнётесь с любыми ошибками в коде, которые вы не знаете , как исправить после прочтения этой статьи, вы можете получить помощь! Спросите на нить обучения Область дискурсе , или в #mdn IRC канал на Mozilla IRC. Расскажите нам, какая у вас ошибка, и мы постараемся вам помочь. Приложите пример своего кода для большей ясности проблемы.
  • Назад
  • Обзор: Первые шаги
  • Далее

Ошибка JavaScript. Как найти и исправить ошибку JavaScript

От автора: приветствую вас, друзья. Из этой небольшой статьи мы с вами узнаем, как увидеть и исправить ошибки JavaScript. Статья написана для начинающих изучение JavaScript.

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

В этой простейшей программе есть ошибка JavaScript, которую нам и нужно найти, поскольку с ней наш код не работает и модальное окно не показывается. Мало того, в JavaScript многие ошибки можно назвать фатальными, поскольку из-за них может прекратить работу не только ваш скрипт, но и сторонние библиотеки JavaScript до тех пор, пока ошибка не будет исправлена.

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

Что же поможет найти ошибки JavaScript? Консоль браузера. Здесь мы вкратце пройдемся по этому инструменту в различных браузерах, в частности это будет Firefox и Chrome. В обоих браузерах консоль есть из коробки.

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

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

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

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

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

Ну и консоль Хрома:

Она также вызывается из контекстного меню или клавишей F12.

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

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

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Смотреть

Существует ряд причин, по которым код JavaScript может вызывать ошибки, например:

  • Проблема с сетевым подключением;
  • Пользователь мог ввести неверное значение в поля формы;
  • Ссылка на объекты или функции, которые не существуют;
  • Неправильные данные отправляются или принимаются с веб-сервера;
  • Служба, к которой приложение должно получить доступ, может быть временно недоступна.

Эти типы ошибок известны как ошибки времени выполнения (runtime errors), поскольку они возникают во время выполнения скрипта. Профессиональное приложение должно иметь возможность корректно обрабатывать такие ошибки во время выполнения. Обычно это означает понятное информирование пользователя о возникшей проблеме.

Оператор try…catch

JavaScript предоставляет оператор try-catch, чтобы перехватывать ошибки времени выполнения и корректно их обработать.

Любой код, который может вызвать ошибку, должен быть помещен в блок оператора try, а код для обработки ошибки помещен в блок catch, как показано здесь:

try {
    // Код, который может вызвать ошибку
} catch(error) {
    // Действие, которое нужно выполнить при возникновении ошибки
}

Если ошибка возникает в любой точке блока try, выполнение кода немедленно переносится из блока try в блок catch. Если в блоке try ошибки не возникает, блок catch будет проигнорирован, и программа продолжит выполнение после оператора try-catch.

Следующий пример демонстрирует, как работает оператор try-catch:

try {
    var greet = "Hi, there!";
    document.write(greet);
    
    // Попытка получить доступ к несуществующей переменной
    document.write(welcome);
    
    // Если произошла ошибка, следующая строка не будет выполнена
    alert("All statements are executed successfully.");
} catch(error) {
    // Обработка ошибки
  alert("Caught error: " + error.message);
}
 
// Продолжаем исполнение кода
document.write("<p>Hello World!</p>");

Приведенный выше скрипт генерирует ошибку, которая отображается в диалоговом окне с предупреждением, а не выводится в консоль браузера. Кроме того, программа не остановилась внезапно, даже если произошла ошибка.

Также обратите внимание, что за ключевым словом catch указывается идентификатор в скобках. Этот идентификатор действует как параметр функции. При возникновении ошибки интерпретатор JavaScript генерирует объект, содержащий сведения о нем. Этот объект ошибки затем передается в качестве аргумента для обработки.

Оператор try-catch является механизмом обработки исключений. Исключением является сигнал, который указывает, что во время выполнения программы возникли какие-то исключительные условия или ошибки. Термины «исключение» и «ошибка» часто используются взаимозаменяемо.

Оператор try…catch…finally

Оператор try-catch также может содержать предложение finally. Код внутри блока finally всегда будет выполняться независимо от того, произошла ошибка в блоке try или нет.

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

// Присвоение значения, возвращаемого диалоговым окном
var num = prompt("Enter a positive integer between 0 to 100");

// Запоминание времени начала исполнения
var start = Date.now();

try {
    if(num > 0 && num <= 100) {
        alert(Math.pow(num, num)); // the base to the exponent power
    } else {
        throw new Error("An invalid value is entered!");
    }
} catch(e) {
    alert(e.message);
} finally {
    // Отображение времени, необходимого для выполнения кода
    alert("Execution took: " + (Date.now() - start) + "ms");
}

Вызов ошибок с помощью оператора throw

До сих пор мы видели ошибки, которые автоматически генерируются парсером JavaScript. Тем не менее, также можно вызвать ошибку вручную с помощью оператора throw.

Общий синтаксис оператора throw: throw expression;

Выражение expression может быть объектом или значением любого типа данных. Однако лучше использовать объекты, желательно со свойствами name и message. Встроенный в JavaScript конструктор Error() предоставляет удобный способ создания объекта ошибки. Давайте посмотрим на некоторые примеры:

throw 123;
throw "Missing values!";
throw true;
throw { name: "InvalidParameter", message: "Parameter is not a number!" };
throw new Error("Something went wrong!");

Если вы используете встроенные в JavaScript функции конструктора ошибок (например, Error(), TypeError() и т. д.) для создания объектов ошибок, тогда свойство name совпадает с именем конструктора, а message равно аргументу функции конструктора.

Теперь мы собираемся создать функцию squareRoot(), чтобы найти квадратный корень числа. Это можно сделать просто с помощью встроенной в JavaScript функции Math.sqrt(), но проблема здесь в том, что она возвращает NaN для отрицательных чисел, не давая никаких подсказок о том, что пошло не так.

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

function squareRoot(number) {
    // Выдает ошибку, если число отрицательное
    if(number < 0) {
        throw new Error("Sorry, can't calculate square root of a negative number.");
    } else {
        return Math.sqrt(number);
    }
}
    
try {
    squareRoot(16);
    squareRoot(625);
    squareRoot(-9);
    squareRoot(100);
    
    // Если выдается ошибка, следующая строка не будет выполнена
    alert("All calculations are performed successfully.");
} catch(e) {
    // Обработка ошибки
    alert(e.message);
}

Теоретически можно вычислить квадратный корень из отрицательного числа, используя мнимое число i, где i2 = -1. Следовательно, квадратный корень из -4 равен 2i, квадратный корень из -9 равен 3i и так далее. Но мнимые числа не поддерживаются в JavaScript.

Типы ошибок

Объект Error является базовым типом всех ошибок и имеет два основных свойства: name, указывающее тип ошибки и свойство message, которое содержит сообщение, описывающее ошибку более подробно. Любая выданная ошибка будет экземпляром объекта Error.

Существует несколько различных типов ошибок, которые могут возникнуть во время выполнения программы JavaScript, например RangeError, ReferenceError, SyntaxError, TypeError, и URIError.

В следующем разделе описывается каждый из этих типов ошибок более подробно:

RangeError

RangeError генерируется, когда вы используете число, выходящее за пределы допустимых значений. Например, создание массива с отрицательной длиной вызовет RangeError.

var num = 12.735;
num.toFixed(200); // выдает ошибку диапазона (допустимый диапазон от 0 до 100)

var array = new Array(-1); // выдает ошибку диапазона

ReferenceError

Ошибка ReferenceError обычно выдается, когда вы пытаетесь сослаться на переменную или объект, которые не существуют, или получить к ним доступ. В следующем примере показано, как происходит ошибка ReferenceError.

var firstName = "Harry";
console.log(firstname); // выдает ошибку ссылки (имена переменных чувствительны к регистру)

undefinedObj.getValues(); // выдает ошибку ссылки

nonexistentArray.length; // выдает ошибку ссылки

SyntaxError

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

var array = ["a", "b", "c"];
document.write(array.slice(2); // выдает синтаксическую ошибку (отсутствует скобка)

alert("Hello World!'); // выдает синтаксическую ошибку (несоответствие кавычек)

TypeError

Ошибка TypeError возникает, когда значение не относится к ожидаемому типу. Например, вызов метода строки для числа, вызов метода массива для строки и т. д.

var num = 123;
num.toLowerCase(); /* выдает ошибку (поскольку toLowerCase() является строковым методом, число не может быть преобразовано в нижний регистр) */

var greet = "Hello World!"
greet.join() // выдает ошибку (так как join() является методом массива)

URIError

URIError генерируется, когда вы указали недопустимый URI (расшифровывается как Uniform Resource Identifier) для функций, связанных с URI, таких как encodeURI() или decodeURI(), как показано здесь:

var a = "%E6%A2%B";
decodeURI(a);  // выдает ошибку URI

var b = "uD800";
encodeURI(b);   // выдает ошибку URI

Существует еще один тип ошибки EvalError, который генерируется при возникновении ошибки во время выполнения кода с помощью функции eval(). Хотя эта ошибка больше не генерируется JavaScript, этот объект все еще остается для обратной совместимости.

Конкретный тип ошибки также может быть выдан вручную с использованием соответствующего конструктора и оператора throw. Например, чтобы сгенерировать ошибку TypeError, вы можете использовать конструктор TypeError(), например:

var num = prompt("Please enter a number");

try {
    if(num != "" && num !== null && isFinite(+num)) {
        alert(Math.exp(num));
    } else {
        throw new TypeError("You have not entered a number.");
    }
} catch(e) {
    alert(e.name);
    alert(e.message);
    alert(e.stack); // нестандартное свойство
}

Объект Error также поддерживает некоторые нестандартные свойства. Одним из наиболее широко используемых таких свойств является: stack trace, который возвращает трассировку стека для этой ошибки. Вы можете использовать его в целях отладки, но не используйте его на рабочих сайтах.

Knowing how to fix JavaScript errors can be very handy for any Windows user. So, if you want to know how to fix it, keep reading.

This article will explain how to get it fixed without much trouble.

A Quick Look at the JavaScript Errors

Here are some important things you should know when it comes to JavaScript errors you might come across.

  • In some cases, JavaScript errors can appear when you start apps such as Discord or Skype. Essentially, this error and many others may be common with chat apps.
  • Among many other errors, “JavaScript error occur in the main process” is a common one.
  • There is no shortage of solutions for those who want to fix JavaScript errors.

Are you passionate about the concept of online chatting? Do you often use chat apps such as Discord or Skype? If so, the possibility of experiencing some JavaScript errors cannot be underestimated.

That is why learning how to fix JavaScript errors is important. If you know how to do it, you will feel no stress when facing such errors.

JavaScript errors don’t occur due to a single reason. In other words, there can be several different reasons. Regardless of the actual cause, it is always possible to address this issue easily.

If you wonder how to fix JavaScript errors and need some guidance, you may follow the guide below.


The Possible Reasons for JavaScript Error

In this section, let’s look at some of the most common reasons for JavaScript errors appearing. Listed below are those possibilities.

  • Your program’s settings or even the program itself might have been corrupted.
  • The service called “Quality Windows Audio Video Experience” is disabled.
  • The respective chat app you intend to open has administrator privileges.

PS: if you are experiencing the Javaw.exe missing errors on your PC, here are the top solutions.


The Best Solutions to Fix JavaScript Errors 

fix JavaScript errors 

Now that you have a better understanding of the nature of this JavaScript error. Let’s learn the solutions. In this case, we will use several solutions. This doesn’t mean that you have to try all of them.

Instead, you can try one after the other until the error is completely resolved. Also, you should remember that there is

01. Perform a Reinstallation of the Respective Program

The first option you should try as a solution to fix JavaScript errors is reinstallation. With a reinstallation, you can expect to fix several errors associated with the respective program. Well, reinstalling a program is a very simple task for any individual.

However, if You Still Want to Learn How to Do It, Mentioned Below Are the Steps to Follow.

As per this method, we assume something is wrong with the existing installation. Also, based on the type of the programs, some of your user files can go missing.

So, if you have some files created with that respective program, you may create a backup of that information. After that, please go ahead with the installation (with the following steps).

  • To begin, you should press the Windows key to bring to the start menu. If not, you can click on the start button. That will bring the Windows Start Menu up.
  • You can enter the program’s name when the start menu is up. For instance, if you want to uninstall Discord, you should enter “Discord.” If it is Skype, just enter the text “Skype.” Likewise, you should simply enter the name of the program.
  • Now, you should right-click on the respective program and choose “Uninstall.”
Skype Uninstall
  • Once the process is completed and the program is uninstalled, you can download the application again. This time, you will download the most recent version of the application.

Please Note That You Will Face Hard Times when Uninstalling Some Applications.

You can use an uninstaller tool if it is difficult to uninstall any of those applications. IObit is one of those tools that can do uninstalling very effectively. This tool can uninstall any stubborn program that doesn’t get uninstalled properly.

So, give it a try and uninstall those faulty programs easily. You can easily download the program, install it, and launch it. Once you have launched it, you will see a button to uninstall the program effortlessly. It will uninstall the program and leave no leftovers.

Basically, IObit can remove any program without leaving any trace whatsoever. Once the complete uninstallation is done, you can reinstall the program. And that’s the first method you can use to fix JavaScript errors.

02. Get Rid of the Folder of the Respective Program from AppData

This is another method you can try if you want to fix JavaScript errors. This is more of the “manual” version of the above uninstallation procedure.

As per this method, you will be manually deleting all the data related to the respective program.  

Please Follow the Below Simple Guide to Delete the Folder from AppData.

  • First, you should launch Windows Explorer. To do that, you can use keyboard shortcuts. Press the “Windows” and “E” keys to launch it.
  • Once the Explorer window is open, you can see a list of icons. All you need is to choose the icon labeled “This PC.”
  • Then, you should navigate to the path mentioned below.

C:Users{Your User Name}AppDataRoaming{Your Program}

  • Now, you should perform right-click on the respective folder of the program. After that, you should select the option called “Delete.”
Delete respective program from Appdata
  • In some cases, there is a possibility of getting an error message when you try to delete it. The message might say that you cannot delete the folder as it is being used. However, you can avoid this error simply by accessing the task manager. Go to the task manager utility and end the faulty task.

That’s it. You can now reinstall the faulty application and see if it works.

03. Set the Service to Be Started Automatically

You can try this option if the previous two options have failed. There is a service called “Start Quality Windows Audio Video Experience.” You will have to set up this specific service automatically on your system.

As a result, you might see that the error is fixed. If you want to learn how to do it, follow the below steps.

  • First, you should launch the “Run” utility on your PC. You should press the “Windows” and “R” keys together to do it.
  • Once the “Run” command is open, you can enter the text “services.msc“.
  • You can go down on the page now. Then, you should see the “Quality Windows Audio Video Experience option.”
  • You can then perform right-click on that option. After that, you should choose the option called “Properties.”
  • When you see the option “Startup Type,” you should see a couple of entries. Choose the option “Automatic” from the dropdown.
Start Service to fix JavaScript errors 

Now, you should perform a restart on your PC. We believe that this method will fix JavaScript errors.

Do You Still Get a JavaScript Error?

In some cases, even if you try to fix JavaScript errors, you may not succeed. If you get any other JavaScript errors, you can follow the steps mentioned below.

  • Press the “Windows” and “R” keys to bring the “Run” utility up.
  • Then, enter the text “services.msc“.
  • Now, scroll down to locate “Quality Windows Audio Video Experience.”
  • Perform a right-click on that and choose “Properties.”
  • Now, go to the option called “Log On.”
  • Click on the option called “Browse.”
  • Now, you will see a box called “Enter.”
  • Provide the name of your Windows account.
  • Choose the option called “Check Names.”
  • Wait for a while and press “OK.”
  • Enter the password in the provided field.
Do You Still Get a JavaScript Error

04. Run the Program As an Administrator

  • Go to the executable file of the program.
  • Perform a right-click on it and click on “Properties.”
  • Choose the option called “Compatibility.”
  • Then, select the box that represents “Run this program as an administrator” to proceed.
  • Hit OK to proceed.
Run Program as administator to fix JavaScript errors 

So, you can try the above steps and see if the problem gets solved. We believe at least one of the above solutions should work and fix JavaScript errors. If you do have other queries, please let us know.

This website uses cookies to ensure you get the best experience on our website

Как исправить распространенные ошибки JavaScript

Ошибки в JavaScript достаточно сложно отслеживать и исправлять. У каждой ошибки есть свое название. Это помогает с определением проблемы и ее исправлением. Необработанные ошибки отображаются в веб-консоли браузера или выводе Node.js приложения. Рассмотрим типы распространенных ошибок в JavaScript, причины возникновения и как их исправить. По каждому типу показаны примеры, чтобы улучшить ваше понимание ошибки и действий для исправления.

Нет единого стандарта именований ошибок в разных браузерах. Для статьи взяты имена ошибок из браузера Google Chrome.

TypeError: Cannot read property “x” of “y”

Пример TypeError: Cannot read property “x” of “y”

Эта ошибка возникает, когда мы вызываем метод или читаем свойство на undefined или null значениях.

В браузере Safari эти ошибки названы по-другому:

  • ‘undefined’ is not an object
  • ‘null’ is not an object

В браузере Mozilla Firefox:

  • TypeError: “x” is undefined
  • TypeError: “x” is null

Примеры ошибок

  • Вызов функции на undefined:
let foo;
foo.read(); // TypeError: Cannot read property 'read' of undefined
  • Чтение свойства на null:
foo = null;
foo.total; // TypeError: Cannot read property 'total of null

Исправление ошибки

Есть несколько вариантов исправления в зависимости от контекста проблемы.

  • Задать значение переменной или свойству объекта перед его использованием.
let foo = {
total: 5
};

let total = foo.total; // 5

  • Проверять, что переменная определена, перед ее использованием.
if (typeof foo !== 'undefined' && typeof foo.total !== 'undefined') {
let total = foo.total;
}

TypeError: “x” is not a function

Пример TypeError: “x” is not a function

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

Примеры ошибок

Есть несколько вариантов исправления в зависимости от причин ошибки:

  • Функция не определена.
let x = {};

x.read(); // TypeError: x.read is not a function

В этом примере определим функцию read().

let x = {
read: function() {
return 2;
}
};

x.read(); // 2

  • В месте вызова или объявлении функции есть опечатка в имени функции.
let a = {
sam: function(a, b) {
return a + b;
}
}

a.sum(1, 1); // TypeError: a.sum is not a function

После исправления опечатки в имени функции sum().

let a = {
sum: function(a, b) {
return a + b;
}
}

a.sum(1, 1); // 2

TypeError: Cannot set property “x” of undefined

Пример TypeError: Cannot set property “x” of undefined

Эта ошибка возникает, когда мы пытаемся записать в свойство undefined значения.

let test;

test.value = 0; // Uncaught TypeError: Cannot set property 'value' of undefined

Решением в данном примере будет инициализация переменной test новым объектом так:

let test = {};

test.value = 0;

Или вот так:

let test = {
value: 0
};

ReferenceError: “x” is not defined

Пример TypeError: ReferenceError: “x” is not defined

Эта ошибка возникает в нескольких случаях.

Переменная не объявлена

text.trim(); // Uncaught ReferenceError: text is not defined

Переменная text не объявлена. Для использования строкового метода trim() переменную text нужно объявить и инициализировать строкой.

let text = " Test ";

text.trim(); // "Test"

Нет доступа к переменной в текущей области видимости

function test() {
let a = 0;
}

console.log(a); // Uncaught ReferenceError: a is not defined

Переменную a нужно сделать доступной для использования там, где происходит ошибка.

let a = 0;

function test() {
a = 1;
}

console.log(a); // 0
test();
console.log(a); // 1

RangeError: Maximum call stack size exceeded

Эта ошибка возникает в случае вызова бесконечной рекурсивной функции. У такой функции нет выхода из нее или он не применяется.

function countDown(fromNumber) {
console.log(fromNumber);

countDown(fromNumber - 1); // RangeError: Maximum call stack size exceeded
}

countDown(10);

Чтобы исправить эту ошибку в рекурсивную функцию countDown() нам нужно добавить условие для выхода из рекурсии.

function countDown(fromNumber) {
console.log(fromNumber);

let nextNumber = fromNumber - 1;

if (nextNumber > 0) {
countDown(nextNumber);
}
}

countDown(10);

RangeError: precision is out of range

Пример RangeError: precision is out of range

Ошибка происходит когда число, выходящее за пределы допустимого диапазона, было передано в функции toExponential(), toFixed(), или toPrecision().

let num = 4.777777;
num.toExponential(-2); // RangeError: toExponential() argument must be between 0 and 100

num = 4.8888;
num.toFixed(105); // RangeError: toFixed() digits argument must be between 0 and 100

num = 4.1234;
num.toPrecision(0); // RangeError: toPrecision() argument must be between 1 and 100

Чтобы исправить, будем использовать допустимые значения.

let num = 4.777777;
num.toExponential(4); // 2.5556e+0

num = 4.8888;
num.toFixed(2); // 3.00

num = 4.1234;
num.toPrecision(1); // 4

RangeError: invalid array length

Пример RangeError: invalid array length

Эта ошибка возникает, если мы задаем массиву недопустимый размер: негативный или больше 232.

new Array(-10); // RangeError: Invalid array length

let a = [];
a.length = a.length - 5; // RangeError: Invalid array length

Для решения данной ошибки нам нужно использовать допустимую длину массива.

new Array(10); // [empty × 10]

Полезные ссылки

JavaScript ссылки на ошибки

Ниже, вы найдёте список ошибок, которые возвращает JavaScript. Эти ошибки могут быть полезны при отладке, но неполадки не всегда сразу понятны. Страницы ниже предлагают дополнительную информацию об этих ошибках. Каждая ошибка это Объект на основании Error object, и имеет имя (name) и сообщение (message).

Mozilla

https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Errors

Резюме

Надеюсь вы узнали что-то новое для себя. И сможете определять причину ошибок в JavaScript и способ их исправления. Эти ошибки могут возникать в рабочих проектах и лучше заранее иметь представление о них.

Спасибо, что прочитали. Буду вам очень признателен если поделитесь этой статьей!

Опубликовано 21 апреля 2021 г.

Опубликовано: среда, 29 марта 2023 г. в 09:06

  • JavaScript

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

Опытные разработчики ожидают неожиданного. Если что-то может пойти не так, так оно и будет — обычно в тот момент, когда первый пользователь получает доступ к вашему новому приложению.

Некоторых ошибок веб-приложений можно избежать, например:

  • Хороший редактор или линтер может отлавливать синтаксические ошибки.
  • Хорошая валидация может выявить ошибки пользовательского ввода.
  • Надёжные процессы тестирования могут обнаруживать логические ошибки.

И всё же ошибки остаются. Браузеры могут сбоить или не поддерживать API, который мы используем. Серверы могут дать сбой или слишком долго отвечать. Сетевое соединение может выйти из строя или стать ненадёжным. Проблемы могут быть временными, но мы не может программировать такие проблемы. Однако мы можем предвидеть проблемы, принимать меры по их устранению и повышать отказоустойчивость нашего приложения.

Отображение сообщения об ошибке — крайняя мера

В идеале пользователи никогда не должны видеть сообщения об ошибке.

Мы можем игнорировать незначительные проблемы, такие как невозможность загрузки декоративного изображения. Мы могли бы решить более серьёзные проблемы, такие как сбои сохранения данных Ajax локально и загружая их позже. Ошибка становиться необходимой только тогда, когда пользователь рискует потерять данные, предполагая, что он может что-то с этим сделать.

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

Как JavaScript обрабатывает ошибки

Когда оператор JavaScript приводит к ошибке, говорят, что он генерирует (выбрасывает) исключение. JavaScript создаёт и выбрасывает объект Error, описывающий ошибку. Мы можем увидеть это в действии на CodePen. Если установить в десятичные разряды (decimal places) отрицательное число, мы увидим сообщение об ошибке в консоли внизу. (Обратите внимание, что мы не встраиваем CodePen в это руководство, потому что нужно иметь возможно видеть вывод консоли, чтобы этот пример имел смысл)

Результат не обновиться, и мы увидим сообщение RangeError в консоли. Следующая функция выдаёт ошибку, когда dp имеет отрицательно значение:

// division calculation
function divide(v1, v2, dp) {

return (v1 / v2).toFixed(dp);

}

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

// show result of division
function showResult() {

result.value = divide(
parseFloat(num1.value),
parseFloat(num2.value),
parseFloat(dp.value)
);

}

Интерпретатор повторяет процесс для каждой функции в стеке вызовов, пока не произойдёт одно из следующих событий:

  • Он находит обработчик исключений.
  • Он достигает верхнего уровня кода (что приводит к завершению программы и отображению ошибки в консоли, как показано в примере на CodePen выше).

Перехват исключений

Мы можем добавить обработчик исключений в функцию divide() с помощью блока try...catch:

// division calculation
function divide(v1, v2, dp) {
try {
return (v1 / v2).toFixed(dp);
}
catch(e) {
console.log(`
error name :
${ e.name }
error message:
${ e.message }
`
);
return 'ERROR';
}
}

Функция выполняет код в блоке try {}, но при возникновении исключения выполняется блок catch {} и получает выброшенный объект ошибки. Как и прежде, попробуйте в decimal places установить отрицательное число в этой демонстрации CodePen.

Теперь result показывает ERROR. Консоль показывает имя ошибки и сообщение, но это выводится оператором console.log и не завершает работу программы.

Примечание: эта демонстрация блока try...catch излишняя для базовой функции, такой как divide(). Как мы увидим ниже, проще убедиться, что dp равен нулю или больше.

Можно определить не обязательный блок finally {}, если требуется, чтобы код запускался при выполнении кода try или catch:

function divide(v1, v2, dp) {
try {
return (v1 / v2).toFixed(dp);
}
catch(e) {
return 'ERROR';
}
finally {
console.log('done');
}
}

В консоль выведется done, независимо от того, успешно ли выполнено вычисление или возникла ошибка. Блок finally обычно выполняет действия, которые в противном случае нам пришлось бы повторять как в блоке try, так и в блоке catch. Например, отмену вызова API или закрытие соединения с базой данных.

Для блока try требуется либо блок catch, либо блок finally, либо и то и другое. Обратите внимание, что когда блок finally содержит оператор return, это значение становится возвращаемым значением для всей функции; другие операторы в блоках try или catch игнорируются.

Вложенные обработчики исключений

Что произойдёт, если мы добавим обработчик исключений к вызывающей функции showResult()?

// show result of division
function showResult() {

try {
result.value = divide(
parseFloat(num1.value),
parseFloat(num2.value),
parseFloat(dp.value)
);
}
catch(e) {
result.value = 'FAIL!';
}

}

Ответ… ничего! Блок catch никогда не выполняется, потому что в функции divide() блок catch обрабатывает ошибку.

Тем не менее мы могли бы программно генерировать новый объект Error в divide() и при желании передать исходную ошибку в свойстве cause второго аргумента:

function divide(v1, v2, dp) {
try {
return (v1 / v2).toFixed(dp);
}
catch(e) {
throw new Error('ERROR', { cause: e });
}
}

Это вызовет блок catch в вызывающей функции:

// show result of division
function showResult() {

try {
//...
}
catch(e) {
console.log( e.message ); // ERROR
console.log( e.cause.name ); // RangeError
result.value = 'FAIL!';
}
}

Стандартные типы ошибок JavaScript

Когда возникает исключение, JavaScript создаёт и выдаёт объект, описывающий ошибку, используя один из следующих типов.

SyntaxError

Ошибка, возникающая из-за синтаксически недопустимого кода, такого как отсутствующая скобка:

if condition) { // SyntaxError
console.log('condition is true');
}

Примечание: такие языки, как C++ и Java, сообщают об ошибках синтаксиса во время компиляции. JavaScript — интерпретируемый язык, поэтому синтаксические ошибки не выявляются до тех пор, пока код не запустится. Любой хороший редактор кода или линтер могут обнаружить синтаксические ошибки до того, как мы попытаемся запустить код.

ReferenceError

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

function inc() {
value++; // ReferenceError
}

Опять, хороший редактор кода или линтер могут обнаружить эту проблему.

TypeError

Ошибка возникает, когда значение не соответствует ожидаемому типу, например, при вызове несуществующего метода объекта:

const obj = {};
obj.missingMethod(); // TypeError

RangeError

Ошибка возникает, когда значение не входит в набор или диапазон допустимых значений. Используемый выше метод toFixed() генерирует эту ошибку, потому что он ожидает значение от 0 до 100:

const n = 123.456;
console.log( n.toFixed(-1) ); // RangeError

URIError

Ошибка выдаваемая функциями обработки URI, такими как encodeURI() и decodeURI(), при обнаружении неправильных URI:

const u = decodeURIComponent('%'); // URIError

EvalError

Ошибка возникающая при передаче строки, содержащей не валидный JavaScript код, в функцию eval():

eval('console.logg x;'); // EvalError

Примечание: пожалуйста, не используйте eval()! Выполнение произвольного кода, содержащегося в строке, возможно, созданной на основе пользовательского ввода, слишком опасно!

AggregateError

Ошибка возникает, когда несколько ошибок объединены в одну ошибку. Обычно возникает при вызове такой операции, как Promise.all(), которая возвращает результаты нескольких промисов.

InternalError

Нестандартная ошибка (только в Firefox) возникает при возникновении внутренней ошибки движка JavaScript. Обычно это результат того, что что-то занимает слишком много памяти, например, большой массив или слишком много рекурсии.

Error

Наконец, есть общий объект Error, чаще всего используемый при реализации собственных исключений… о котором мы поговорим дальше.

Генерация/выбрасывание собственных исключений

Мы можем использовать throw для генерации/выбрасывания собственных исключений, когда возникает ошибка — или должна произойти. Например:

  • нашей функции не передаются валидные параметры
  • ajax-запрос не возвращает ожидаемые данные
  • обновление DOM завершается ошибкой, поскольку узел не существует

Оператор throw фактически принимает любое значение или объект. Например:

throw 'A simple error string';
throw 42;
throw true;
throw { message: 'An error', name: 'MyError' };

Исключения генерируются для каждой функции в стеке вызовов до тех пор, пока они не будут перехвачены обработчиком исключений (catch). Однако на практике мы хотим создать и сгенерировать объект Error, чтобы он действовал идентично стандартным ошибкам, выдаваемым JavaScript.

Можно создать общий объект Error, передав необязательное сообщение конструктору:

throw new Error('An error has occurred');

Так же Error можно использовать как функцию, без new. Она возвращает объект Error, идентичный приведённому выше:

throw Error('An error has occurred');

При желании можно передать имя файла и номер строки в качестве второго и третьего параметров:

throw new Error('An error has occurred', 'script.js', 99);

В этом редко возникает необходимость, так как по умолчанию они относятся к файлу и строке, где мы вызвали объект Error. (Также их сложно поддерживать, поскольку наши файлы меняются!)

Мы можем определить общие объекты Error, но по возможности следует использовать стандартный тип Error. Например:

throw new RangeError('Decimal places must be 0 or greater');

Все объекты Error имеют следующие свойства, которые можно проверить в блоке catch:

  • .name: имя типа ошибки, например Error или RangeError.
  • .message: сообщение об ошибке.

В Firefox поддерживаются следующие нестандартные свойства:

  • .fileName: файл, в котором произошла ошибка.
  • .lineNumber: номер строки, в которой произошла ошибка.
  • .columnNumber: номер столбца, в котором произошла ошибка.
  • .stack: трассировка стека со списком вызовов функций, сделанных до возникновения ошибки.

Мы можем изменить функцию divide() так, чтобы она вызывала ошибку RangeError, когда количество знаков после запятой не является числом, меньше нуля и больше восьми:

// division calculation
function divide(v1, v2, dp) {

if (isNaN(dp) || dp < 0 || dp > 8) {
throw new RangeError('Decimal places must be between 0 and 8');
}

return (v1 / v2).toFixed(dp);
}

Точно так же мы могли бы выдать Error или TypeError, когда значения делимого не является числом, чтобы предотвратить результат NaN:

  if (isNaN(v1)) {
throw new TypeError('Dividend must be a number');
}

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

// new DivByZeroError Error type
class DivByZeroError extends Error {
constructor(message) {
super(message);
this.name = 'DivByZeroError';
}
}

Затем вызывать/выбрасывать его подобным образом:

if (isNaN(v2) || !v2) {
throw new DivByZeroError('Divisor must be a non-zero number');
}

Теперь добавьте блок try...catch к вызывающей функции showResult(). Он сможет получить тип любой ошибки и отреагировать соответствующим образом — в данном случае, выводя сообщение об ошибке:

// show result of division
function showResult() {

try {
result.value = divide(
parseFloat(num1.value),
parseFloat(num2.value),
parseFloat(dp.value)
);
errmsg.textContent = '';
}
catch (e) {
result.value = 'ERROR';
errmsg.textContent = e.message;
console.log( e.name );
}

}

Попробуйте ввести недопустимые нечисловые, нулевые и отрицательные значения в демонстрации на CodePen.

Окончательная версия функции divide() проверяет все входящие значения и при необходимости выдаёт соответствующую ошибку:

// division calculation
function divide(v1, v2, dp) {

if (isNaN(v1)) {
throw new TypeError('Dividend must be a number');
}

if (isNaN(v2) || !v2) {
throw new DivByZeroError('Divisor must be a non-zero number');
}

if (isNaN(dp) || dp < 0 || dp > 8) {
throw new RangeError('Decimal places must be between 0 and 8');
}

return (v1 / v2).toFixed(dp);
}

Больше нет необходимости размещать блок try...catch вокруг финального return, так как он никогда не должен генерировать ошибку. Если бы это произошло, JavaScript сгенерировал бы свою собственную ошибку и обработал бы её блоком catch в showResult()/

Ошибки асинхронной функции

Мы не можем перехватывать исключения, генерируемые асинхронными функциями на основе обратного вызова, потому что после завершения выполнения блока try...catch выдаётся ошибка. Этот код выглядит правильно, но блок catch никогда не выполнится, и через секунду консоль отобразит сообщение Uncaught Error:

function asyncError(delay = 1000) {

setTimeout(() => {
throw new Error('I am never caught!');
}, delay);

}

try {
asyncError();
}
catch(e) {
console.error('This will never run');
}

Соглашение, принятое в большинстве фреймворков и серверных сред выполнения, таких как Node.js, заключается в том, чтобы возвращать ошибку в качестве первого параметра функции обратного вызова. Это не приведёт к возникновению исключения, хотя при необходимости мы можем вручную сгенерировать ошибку:

function asyncError(delay = 1000, callback) {

setTimeout(() => {
callback('This is an error message');
}, delay);

}

asyncError(1000, e => {

if (e) {
throw new Error(`error: ${ e }`);
}

});

Ошибки на основе промисов

Обратные вызовы могут стать громоздкими, поэтому при написании асинхронного кода предпочтительнее использовать промисы. При возникновении ошибки метод reject() промиса может вернуть новый объект Error или любое другое значение:

function wait(delay = 1000) {

return new Promise((resolve, reject) => {

if (isNaN(delay) || delay < 0) {
reject( new TypeError('Invalid delay') );
}
else {
setTimeout(() => {
resolve(`waited ${ delay } ms`);
}, delay);
}

})

}

Примечание: функции должны быть либо 100% синхронными, либо 100% асинхронными. Вот почему необходимо проверять значение delay внутри возвращаемого промиса. Если бы мы проверили значение delay и выдали ошибку перед возвратом промиса, функция стала бы синхронной при возникновении ошибки.

Метод Promise.catch() выполняется при передаче недопустимого параметра delay и получает возвращённый объект Error:

// invalid delay value passed
wait('INVALID')
.then( res => console.log( res ))
.catch( e => console.error( e.message ) )
.finally( () => console.log('complete') );

Я считаю цепочки промисов немного сложными для чтения. К счастью, мы можем использовать await для вызова любой функции, возвращающей промис. Это должно происходить внутри асинхронной функции, но мы можем перехватывать ошибки с помощью стандартного блока try...catch.

Следующая (вызываемая немедленно) асинхронная функция функционально идентична цепочке промисов выше:

(async () => {

try {
console.log( await wait('INVALID') );
}
catch (e) {
console.error( e.message );
}
finally {
console.log('complete');
}

})();

Исключительная обработка исключения

Выбрасывать объекты Error и обрабатывать исключения в JavaScript легко:

try {
throw new Error('I am an error!');
}
catch (e) {
console.log(`error ${ e.message }`)
}

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

Дополнительная информация:

  • MDN Порядок выполнения и обработка ошибок
  • MDN try…catch
  • MDN Error

Добавить комментарий