Статьи

Бросаем лучшие ошибки с помощью стека

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

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

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

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

Итак, мы можем получить эту информацию?

Действительно, мы можем, по крайней мере, в Firefox. Браузеры Firefox и WebKit (Safari, Chrome и т. Д.) Предоставляют свойство stack В нем перечислены все отдельные операторы, которые привели к ошибке: от того места, где она действительно произошла, до любых вызывающих операторов до самой высокой абстракции или события.

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

 function fail(message){   var inputerror = new Error();   inputerror.name = "nMyScript/ValidationError: ";   inputerror.message = message;   if(typeof inputerror.stack != "undefined")   {      var errorstack = inputerror.stack.split(/s*(@|at)s*/);      errorstack = errorstack[errorstack.length - 1]                   .replace(/^s+|s+$/g, '')                   .split(/:([0-9]+)/);      inputerror.fileName = errorstack[0];      inputerror.lineNumber = errorstack[1];   }   return inputerror;}

Это будет тогда использоваться так:

 throw(fail("Illegal value for foo"));

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

По крайней мере, в Firefox!

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

Но все тестируют в Firefox, не так ли? Независимо от того, что используется для просмотра!

Миниатюра кредита: kagey_b

примечание: хотите больше?

Если вы хотите узнать больше от Джеймса, подпишитесь на нашу еженедельную техническую новостную рассылку Tech Times .