For some reason this code gives me an uncaught exception error. It seems the catch block is not catching the error. Are try catch blocks scoped in such a way that I cannot throw an error in a nested function, and then expect it to be caught by a catch statement scoped higher up the chain? Some of the sensitive data with in the application that i’m working in has been removed, but it expected that leadInfo[ 0 / 1] would be a 32 character alpha numeric string that I pull from URL parameters.
The underlying issue here is with my AJAX call returning an error from the API and that error not being handled properly within the application. Hence the need for the throw statement. The AJAX call completes fine, and returns a JSON object that does not contain the email address as a property, so I need to handle that in a way that changes the page to reflect that.
jQuery(document).ready(function(){
try {
url = "http://api.com/api/v1/lead/" + leadInfo[1]
jQuery.ajax({
type: 'GET',
contentType: 'application/json',
url: url,
dataType : 'jsonp',
success: function (result) {
result = jQuery.parseJSON(result);
if(!result.data.email){
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
}
});
jQuery('.surveryButton').click(function(){
window.location.replace("http://" + pgInventory.host + pgInventory.path + leadInfo[0] + "&curLeadId=" + leadInfo[1] + "&curViewedPages=0");
});
}
catch(err) {
jQuery('.email').html('your e-mail address');
jQuery('#arrowContent').remove();
}
});
flavian
28.1k11 gold badges65 silver badges105 bronze badges
asked May 1, 2013 at 10:55
1
The reason why your try catch block is failing is because an ajax request is asynchronous. The try catch block will execute before the Ajax call and send the request itself, but the error is thrown when the result is returned, AT A LATER POINT IN TIME.
When the try catch block is executed, there is no error. When the error is thrown, there is no try catch. If you need try catch for ajax requests, always put ajax try catch blocks inside the success callback, NEVER outside of it.
Here’s how you should do it:
success: function (result) {
try {
result = jQuery.parseJSON(result);
if (!result.data.email) {
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
} catch (exception) {
console.error("bla");
};
}
answered May 1, 2013 at 10:58
flavianflavian
28.1k11 gold badges65 silver badges105 bronze badges
3
Due to the asynchronous nature of the callback methods in javascript, the context of the function throwing the error is different compared to the original one. You should do this way:
success: function (result) {
try {
result = jQuery.parseJSON(result);
if(!result.data.email){
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
}
catch(err) {
// Dealing with the error
}
}
I would suggest you to have a look at this excellent article about the (very particular) contexts, closures and bindings in Javascript.
answered May 1, 2013 at 11:02
jap1968jap1968
7,7271 gold badge30 silver badges37 bronze badges
0
The problem is that ajax is asynchronous by definition. Your exception does not get thrown from within the $.ajax function, but from the callback function on success (which is triggered at a later time).
You should give an error: function(data) {} parameter to it as well, to handle server response errors, and furthermore you should place the try/catch block inside the callback function.
If you really want to catch it outside the callback, then you should consider calling a function rather than throwing an exception, because I don’t see how it can be done.
BenMorel
34.1k49 gold badges179 silver badges319 bronze badges
answered May 1, 2013 at 10:59
MarioDSMarioDS
12.9k15 gold badges65 silver badges121 bronze badges
I am trying to run this Example #1 from this page: http://php.net/manual/en/language.exceptions.php
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
return 1/$x;
}
try {
echo inverse(5) . "n";
echo inverse(0) . "n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "n";
}
// Continue execution
echo "Hello Worldn";
?>
However instead of the desired output I get:
0.2
Fatal error: Uncaught exception 'Exception' with message 'Division by zero.'
in xxx:
7 Stack trace: #0 xxx(14): inverse(0) #1 {main} thrown in xxx on line 7
The developer environment I am using is UniServer 3.5 with PHP 5.2.3
![]()
asked Jan 31, 2010 at 18:09
5
I just had this exact problem where it seemed like I had even copied the name of the exception and yet it didn’t catch it. It turned out it was my stupid mistake but I thought I should post my case here in case there is someone else in the same situation.
I had my exception in my namespace called A and the script was in a namespace called B. The problem was that I had AMyException which equals (in PHP) BAMyException (because my script is in the namespace called B!). All I had to do to fix it was to add backslash (or whatever it’s called) to the exception name so it would look like this: AMyException
answered Oct 25, 2011 at 16:56
PijusnPijusn
11k7 gold badges57 silver badges76 bronze badges
2
Quite old question, yet…
I had this problem as well (and that’s how I found this post) but just simple experiment allowed me to find the solution. Just try changing Exception to Exception. Worked for me!
EDIT:
As sivann pointed in the comments, using namespace should do the same thing. So simply put use Exception as Exception; before your class declaration.
answered Dec 10, 2015 at 19:35
![]()
EnethionEnethion
1,1899 silver badges9 bronze badges
2
Try to put catch(Exception $e) instead of catch(Exception $e) . If you are using a code you don’t know about very well, or — especially — if you are using a framework, it might override the default PHP Exception with one of its own, and therefore you might go to the wrong path and get the undesired result. If you just put Exception , then you are sure you are catching the base PHP exception.
answered Apr 20, 2017 at 8:52
0
You can not use the typical try{} catch{} blocks in PHP as you could do in another language like C# (Csharp).
If you do this:
try{
//division by zero
$number = 5/0;
}
catch(Exception $ex){
echo 'Got it!';
}
You will not see the ‘Got it!’ message never. Why? It’s just because PHP always needs an Exception to be «Thrown». You need to set your own error handler and throw an Exception with it.
See set_error_handler function: http://php.net/manual/es/function.set-error-handler.php
answered Oct 29, 2011 at 1:04
4
If you are using PHP 7, you may need Throwable instead of Exception
answered Mar 20, 2020 at 4:42
3
In my case, a weird situation occurred and catching Exception didn’t work even when I had Exception. Here is what to do to make sure that you never miss anything and always catch the error.
catch (Exception $e) {
// do what you want to do on exception catching
} catch (Throwable $e) {
// do what you want to do on exception catching
}
When you combine these two, you will never miss catching an Exception. Make sure to put the before Exception and Throwable. That’s important.
Edit
An efficient way to catch them would be this
catch (Exception|Throwable $e) {
// do what you want
}
This will catch that without you having two separate catch blocks
answered Oct 22, 2021 at 9:09
![]()
Koushik DasKoushik Das
9,4403 gold badges50 silver badges49 bronze badges
My initial though is you have a typo in the name of the exception you are catching/throwing, but if your code is exactly the same I’m not sure exactly what is going on.
Try the following modification of the original script, and paste your results. It will help diagnose your issue a bit better.
<?php
//set up exception handler to report what we didn't catch
function exception_handler($exception) {
if($exception instanceof MyException) {
echo "you didn't catch a myexception instancen";
} else if($exception instanceof Exception) {
echo "you didn't catch a exception instancen";
} else {
echo "uncaught exception of type: ".gettype($exception)."n";
}
echo "Uncaught exception: " , $exception->getMessage(), "n";
}
//install the handler
set_exception_handler('exception_handler');
class MyException extends Exception {
}
function inverse($x) {
if (!$x) {
throw new MyException('Division by zero.');
}
else return 1/$x;
}
try {
echo inverse(5) . "n";
echo inverse(0) . "n";
} catch (MyException $e) {
echo 'Caught myexception: ', $e->getMessage(), "n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "n";
}
// Continue execution
echo 'Hello World';
?>
answered Jan 31, 2010 at 23:11
sfrenchsfrench
9105 silver badges9 bronze badges
I had the same problem with following configurations,
PHP 5.2.14 (cli) (built: Aug 12 2010 17:32:30)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies
with eAccelerator v0.9.5.1, Copyright (c) 2004-2006 eAccelerator, by eAccelerator
The solution is to either disable eAccelerator or update it. I tried both and both of the fixes worked. The bug is reported here https://eaccelerator.net/ticket/242 (NB. firefox complains about their SSL cert) .
Now I am running try catch properly with following configurations,
PHP 5.2.4 (cli) (built: Oct 16 2007 09:13:35)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
with eAccelerator v0.9.6.1, Copyright (c) 2004-2010 eAccelerator, by eAccelerator
![]()
Darren Cook
27.6k13 gold badges114 silver badges215 bronze badges
answered Dec 20, 2010 at 8:17
YawarYawar
411 bronze badge
catch all exception in php
try
{
//place code
throw new Exception('foo');//eg
}
catch (Throwable $e)
{
dd('for php 7');
} catch (Exception $e)
{
dd('for php 5');
}
https://www.php.net/manual/en/language.exceptions.php
answered Mar 5, 2021 at 16:34
BalajiBalaji
9,2855 gold badges43 silver badges47 bronze badges
in Xdebug there is a setting:
xdebug.show_exception_trace = 1
This will force php to output exceptions even in a try catch block.
Turn this to 0
![]()
pearcoding
1,1491 gold badge9 silver badges28 bronze badges
answered Nov 3, 2013 at 16:48
2
TLDR; make sure you have use Exception; on the top of both php files
answered Mar 25, 2020 at 14:26
![]()
Mr HeelisMr Heelis
2,3404 gold badges23 silver badges33 bronze badges
I am experiencing this as well. I read comment from Rowinson Gallego which state Exception must be thrown. So I modified my code from :
try
{
$number = 5/0; //or other exception
}
catch(Exception $e)
{
throw $e;
}
into :
try
{
$number = 5/0; //or other exception
}
catch(Exception $e)
{
throw new Exception($e->getMessage(),$e->getCode());
}
It works.
answered May 11, 2020 at 13:06
Again this old thread revisited…
I had not require_once’d the file containing my Exception subclass in the file with the try/catch block.
Somehow (maybe due to composer’s autoload) this didn’t result in a ‘cannot be resolved to a type’ error. And somehow my exception was being created with the expected namespace (in yet another file without the require_once). But it wasn’t caught. My directory structure does not match the namespaces so autoload might have loaded the correct class in the file with the try/catch but under a different namespace.
answered Mar 11, 2022 at 23:08
gladdgladd
375 bronze badges
Try to add a backslash before the class for example:
BEFORE
try {
if ($this->customerAuth->authenticate($customerId, $password)) {
$this->session->loginById($customerId);
}
} catch(MagentoFrameworkExceptionStateUserLockedException $e) {
return $this->respondWithCode('login', 401);
} catch (MagentoFrameworkExceptionInvalidEmailOrPasswordException $e) {
return $this->respondWithCode('login', 401);
}
AFTER
try {
if ($this->customerAuth->authenticate($customerId, $password)) {
$this->session->loginById($customerId);
}
} catch(MagentoFrameworkExceptionStateUserLockedException $e) {
return $this->respondWithCode('login', 401);
} catch (MagentoFrameworkExceptionInvalidEmailOrPasswordException $e) {
return $this->respondWithCode('login', 401);
}
answered Apr 4, 2022 at 12:10
![]()
BlackBlack
17.8k39 gold badges156 silver badges268 bronze badges
if (!city) {
let fetchResult;
try {
const url = `https://ipinfo.io/json?token=${APIKEYS.ipinfo}`;
fetchResult = await fetch(url)
} catch (err) {
console.log('hello');
this.city = 'Minsk';
return false;
}
Почему в таком блоке не отлавливается ошибка возникающая при fetch?
-
Вопрос заданболее трёх лет назад
-
1215 просмотров
Вы какую ошибку пытаетесь отловить?
При 404 ошибке fetch все равно завершится доожным образом просто вернет код отличный от 200 и не OK
https://developer.mozilla.org/en-US/docs/Web/API/F…
https://developer.mozilla.org/en-US/docs/Web/API/F…
const url = `https://ipinfo.io/json`;
fetch(url).then(response => {
console.log(response.status, response.ok)
if (response.ok) {
response.json().then(data => {
console.log(data)
})
}
})
const url = `https://ipinfo.io/jsonson`;
fetch(url).then(response => {
console.log(response.status, response.ok)
if (response.ok) {
response.json().then(data => {
console.log(data)
})
}
})
Если бы fetch кидал ошибку, вы бы ее отловили
function some() {
return Promise.reject("Hello")
}
async function f() {
try {
return await some();
} catch (error) {
console.log("Error", error)
}
}
f().then(data => {
console.log("Data", data)
});
Пригласить эксперта
Если хотите сахарно работать с запросами в trycatch стиле посмотрите на axios.
Он такой код как:
async getData() {
try {
const { data } = axios.get('/url')
}catch(e) {
console.error(e)
}
}
Обработает так как вы того ждете. Но сразу скажу, что в данном контексте он делает что-то вроде:
async getData() {
try{
const response = fetch('/url')
if(response.status>= 400 && response.status<= 599) throw new Error(`Http exeption code: ${response.status}`)
}catch(e){
console.error(e)
}
}
-
Показать ещё
Загружается…
22 июн. 2023, в 09:14
20000 руб./за проект
22 июн. 2023, в 09:12
2000 руб./за проект
22 июн. 2023, в 09:08
500 руб./за проект
Минуточку внимания
|
Cvetlana_tan 1 / 1 / 0 Регистрация: 14.01.2017 Сообщений: 8 |
||||
|
1 |
||||
|
15.01.2017, 20:37. Показов 11485. Ответов 11 Метки try/catch (Все метки)
Добрый вечер! Столкнулась с такой проблемой — при вводе некорректного значения в текстбокс, защитный блок try…catch не работает. Хотелось бы узнать причину… Может кто чего подскажет… Код представлен:
0 |
|
910 / 814 / 332 Регистрация: 03.02.2015 Сообщений: 5,249 Записей в блоге: 9 |
|
|
15.01.2017, 21:26 |
2 |
|
Cvetlana_tan, и что пишет ?
0 |
|
1 / 1 / 0 Регистрация: 14.01.2017 Сообщений: 8 |
|
|
15.01.2017, 21:31 [ТС] |
3 |
|
Sanya_sa, Миниатюры
1 |
|
1 / 1 / 0 Регистрация: 14.01.2017 Сообщений: 8 |
|
|
15.01.2017, 21:33 [ТС] |
4 |
|
Sanya_sa, Если запускать без отладки, то всё работает. А так — нет(
0 |
|
910 / 814 / 332 Регистрация: 03.02.2015 Сообщений: 5,249 Записей в блоге: 9 |
|
|
15.01.2017, 21:37 |
5 |
|
Sanya_sa, Если запускать без отладки, то всё работает. А так — нет( Думаю настройки студии.
1 |
|
1 / 1 / 0 Регистрация: 14.01.2017 Сообщений: 8 |
|
|
15.01.2017, 21:39 [ТС] |
6 |
|
Хорошо, спасибо за ответ!
0 |
|
910 / 814 / 332 Регистрация: 03.02.2015 Сообщений: 5,249 Записей в блоге: 9 |
|
|
15.01.2017, 21:42 |
7 |
|
1 |
|
17230 / 12680 / 3323 Регистрация: 17.09.2011 Сообщений: 20,952 |
|
|
16.01.2017, 13:52 |
8 |
|
РешениеCvetlana_tan, на скриншоте видна очень интересная галочка: «Остановить при возникновении исключения этого типа».
1 |
|
1 / 1 / 0 Регистрация: 14.01.2017 Сообщений: 8 |
|
|
16.01.2017, 14:22 [ТС] |
9 |
|
kolorotur, Большое спасибо, все заработало!
0 |
|
0 / 0 / 0 Регистрация: 17.04.2017 Сообщений: 4 |
|
|
20.04.2017, 13:06 |
10 |
|
В случае снятия галочки «Остановить при возникновении исключения этого типа» исключение будет игнорироваться даже вне блока try catch. А как заставить студию ловить исключения только вне блока?
0 |
|
17230 / 12680 / 3323 Регистрация: 17.09.2011 Сообщений: 20,952 |
|
|
20.04.2017, 15:47 |
11 |
|
В случае снятия галочки «Остановить при возникновении исключения этого типа» исключение будет игнорироваться даже вне блока try catch. Не будет.
0 |
|
0 / 0 / 0 Регистрация: 17.04.2017 Сообщений: 4 |
|
|
21.04.2017, 16:22 |
12 |
|
Не будет. У меня как раз таки возникла подобная ситуация. Visual Studio как будто совсем перестал видеть блоки try catch в моем проекте во время отладки. Подробнее расписал в отдельной теме:
0 |
|
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
21.04.2017, 16:22 |
|
12 |
Я работаю над проектом, используя АНТЛР библиотека парсеров для C #. Я построил грамматику для анализа текста, и она хорошо работает. Однако, когда синтаксический анализатор обнаруживает недопустимый или неожиданный токен, он выдает одно из многих исключений. Проблема в том, что в некоторых случаях (не во всех) мой блок try / catch не может его поймать и вместо этого останавливает выполнение как необработанное исключение.
Проблема для меня в том, что я не могу воспроизвести эту проблему где-либо еще, кроме как в моем полном коде. Стек вызовов показывает, что исключение определенно возникает в моем блоке try / catch (Exception). Единственное, о чем я могу думать, это то, что между моим кодом и кодом, генерирующим исключение, происходит несколько вызовов сборки ANTLR, и в этой библиотеке не включена отладка, поэтому я не могу пройти через нее. Интересно, запрещают ли не отлаживаемые сборки пузыри исключений? Стек вызовов выглядит так: вызовы внешней сборки находятся в Antlr.Runtime:
Expl.Itinerary.dll! TimeDefLexer.mTokens () Строка 1213 C # Antlr3.Runtime.dll! Antlr.Runtime.Lexer.NextToken () + 0xfc байтов Antlr3.Runtime.dll! Antlr.Runtime.CommonTokenStream.FillBuffer () + 0x22c bytes Antlr3.Runtime.dll! Antlr.Runtime.CommonTokenStream.LT (int k = 1) + 0x68 байт Expl.Itinerary.dll! TimeDefParser.prog () Строка 109 + 0x17 байт C # Expl.Itinerary.dll! Expl.Itinerary.TDLParser .Parse (string Text = "", Expl.Itinerary.IItinerary Itinerary = {Expl.Itinerary.MemoryItinerary}) Строка 17 + 0xa байтов C #
Фрагмент кода из самого нижнего вызова в Parse () выглядит так:
try {
// Execution stopped at parser.prog()
TimeDefParser.prog_return prog_ret = parser.prog();
return prog_ret == null ? null : prog_ret.value;
}
catch (Exception ex) {
throw new ParserException(ex.Message, ex);
}
На мой взгляд, предложение catch (Exception) должно было фиксировать любое исключение. Есть ли причина, по которой это не так?
Обновление: Я проследил внешнюю сборку с помощью Reflector и не обнаружил никаких доказательств наличия резьбы. Сборка кажется просто служебным классом времени выполнения для кода, сгенерированного ANTLR. Исключение создается методом TimeDefLexer.mTokens (), его тип — NoViableAltException, который является производным от RecognitionException -> Exception. Это исключение возникает, когда лексер не может понять следующий токен в потоке; другими словами, неверный ввод. Это исключение должно произойти, но оно должно было быть обнаружено моим блоком try / catch.
Кроме того, повторное генерирование ParserException действительно не имеет отношения к этой ситуации. Это уровень абстракции, который принимает любое исключение во время синтаксического анализа и преобразует его в мое собственное исключение ParserException. Проблема с обработкой исключений, с которой я столкнулся, никогда не достигает этой строки кода. Фактически, я закомментировал часть «выбросить новое исключение ParserException» и все равно получил тот же результат.
Еще одна вещь: я изменил исходный рассматриваемый блок try / catch, чтобы вместо этого перехватить NoViableAltException, исключив любую путаницу наследования. Я все равно получил тот же результат.
Кто-то однажды предположил, что иногда VS слишком активен при перехвате обработанных исключений в режиме отладки, но эта проблема также возникает в режиме выпуска.
Чувак, я все еще в тупике! Я не упоминал об этом раньше, но я использую VS 2008, и весь мой код — 3.5. Внешняя сборка — 2.0. Кроме того, некоторые из моих кодов являются подклассами класса сборки 2.0. Может ли несовпадение версий вызвать эту проблему?
Обновление 2: Мне удалось устранить конфликт версий .NET, перенеся соответствующие части моего кода .NET 3.5 в проект .NET 2.0 и воспроизведя тот же сценарий. Мне удалось воспроизвести одно и то же необработанное исключение при последовательной работе в .NET 2.0.
Я узнал, что ANTLR недавно выпустил 3.1. Итак, я обновился с 3.0.1 и повторил попытку. Оказывается, сгенерированный код немного переработан, но в моих тестовых примерах возникает то же необработанное исключение.
Обновление 3:
Я воспроизвел этот сценарий в упрощенный проект VS 2008. Не стесняйтесь скачивать и проверять проект на себе. Я применил все замечательные предложения, но пока не смог преодолеть это препятствие.
Если вы можете найти обходной путь, поделитесь своими выводами. Спасибо еще раз!
Спасибо, но VS 2008 автоматически прерывается при необработанных исключениях. Кроме того, у меня нет диалогового окна «Отладка-> Исключения». Вызываемое исключение NoViableAltException полностью предназначено и предназначено для перехвата пользовательским кодом. Поскольку он не перехватывается должным образом, выполнение программы неожиданно останавливается как необработанное исключение.
Выброшенное исключение является производным от Exception, и многопоточность с ANTLR не выполняется.
Конструкция try...catch пытается выполнить инструкции в блоке try, и, в случае ошибки, выполняет блок catch.
Синтаксис
try {
try_statements
}
[catch (exception_var_1 if condition_1) { // не стандартно
catch_statements_1
}]
...
[catch (exception_var_2) {
catch_statements_2
}]
[finally {
finally_statements
}]
try_statements-
Инструкции для выполнения.
catch_statements_1,catch_statements_2-
Инструкции, которые будут выполнены, если произойдёт ошибка в блоке
try.
exception_var_1,exception_var_2-
Идентификатор для хранения объекта ошибки, который впоследствии используется в блоке
catch
condition_1-
Условное выражение.
finally_statements-
Инструкции, которые выполняются после завершения блока
try. Выполнение происходит в независимости от того, произошла ошибка или нет.
Описание
Конструкция try содержит блок try, в котором находится одна или несколько инструкций (Блок ({} ) обязательно должен присутствовать, даже если выполняется всего одна инструкция), и хотя бы один блок catch или finally. Таким образом, есть три основные формы конструкции try:
try {...} catch {...}try {...} finally {...}try {...} catch {...} finally {...}
Блок catch содержит инструкции, которые будут выполнены, если в блоке try произошла ошибка. Если любая инструкция в блоке try выбрасывает исключение, то управление сразу же переходит в блок catch. Если в блок try не было выброшено исключение, то блок catch не выполняется.
Блок finally выполнится после выполнения блоков try и catch, но перед инструкциями, следующими за конструкцией try...catch. Он выполняется всегда, в независимости от того, было исключение или нет.
Вы можете использовать вложенные конструкции try. Если внутренняя конструкция try не имеет блока catch (такое может быть при её использовании в виде try {...} finaly {...}, потому что try {...} не может быть без блоков catch или finally), будет вызван сatch внешней конструкции try.
Конструкция try также используется для обработки исключений JavaScript (то есть, выброшенных внутренними функциями языка или парсером). Загляните в JavaScript руководство для дополнительной информации о JavaScript исключениях.
Безусловный блок catch
При использовании блока catch, он вызывается для любого исключения в блоке try. Например, когда в следующем коде происходит ошибка, управление переходит к блоку catch.
try {
throw 'myException'; // создание исключения
}
catch (e) {
// инструкции для обработки ошибок
logMyErrors(e); // передать объект исключения обработчику ошибок
}
Блок catch задаёт идентификатор (e в примере выше) который содержит объект исключения (в примере выше — значение, переданное оператору throw). Область видимости этого объекта ограничивается блоком catch.
Условный блок catch
«Условные блоки catch» можно создавать, используя try...catch с if...else if...else, как здесь:
try {
myroutine(); // может выбрасывать три вида исключений
} catch (e) {
if (e instanceof TypeError) {
// обработка исключения TypeError
} else if (e instanceof RangeError) {
// обработка исключения RangeError
} else if (e instanceof EvalError) {
// обработка исключения EvalError
} else {
// обработка остальных исключений
logMyErrors(e); // передать обработчику ошибок
}
}
Частый сценарий использования — обработать известные исключения, а при неизвестных ошибках, пробросить их дальше:
try {
myRoutine();
} catch(e) {
if (e instanceof RangeError) {
// обработка известного исключения, с которым
// понятно, что делать
} else {
throw e; // пробросить неизвестные ошибки
}
}
Примечание: Обратите внимание: Firefox раньше поддерживал краткую запись условных блоков catch:
try {
myroutine(); // может выбрасывать три вида исключения
} catch (e if e instanceof TypeError) {
// обработка исключений TypeError
} catch (e if e instanceof RangeError) {
// обработка исключений RangeError
} catch (e if e instanceof EvalError) {
// обработка исключений EvalError
} catch (e) {
// обработка остальных исключения
logMyErrors(e);
}
Однако, такой синтаксис никогда не был частью спецификации ECMAScript и был удалён из Firefox после версии 59. Сейчас он не поддерживается ни в одном браузере.
Идентификатор исключения
Когда в блоке try выбрасывается исключение, exception_var (т. е. e в конструкции catch (e)) содержит значение исключения. Его можно использовать, чтобы получить больше информации об выброшенном исключении. Идентификатор доступен только в области видимости блока catch.
try {
if (!firstValidation()) {
throw 1;
}
if (!secondValidation()) {
throw 2;
}
} catch (e) {
// Выводит 1 или 2 (если не произошло никаких других ошибок)
console.log(e);
}
Блок finally
Блок finally содержит код который будет запущен после кода в блоках try и catch. Обратите внимание, что код в блоке finally запускается в независимости от того, было ли выброшено исключение или нет. Также код в блоке finally будет запущен вне зависимости от того, присутствует блок catch или нет. Блок finally можно использовать для того, чтобы скрипт безопасно завершил работу в случае ошибки. Например, если необходимо освободить память и ресурсы которые использовал скрипт.
Наличие специального блока, связанного с ошибкой, который выполняется вне зависимости от наличия исключительной ситуации, может показаться странным, но эта конструкция на самом деле весьма полезна. Рассмотрим пример кода:
function expensiveCalculations() {
// Сложные вычисления
}
function maybeThrowError() {
// Функция, которая может выбросить исключение
if(Math.random() > 0.5) throw new Error()
}
try {
// Теперь при прокрутке страницы будут происходить
// сложные вычисления, что сильно скажется на
// производительности
window.addEventListener('scroll', expensiveCalculations)
maybeThrowError()
} catch {
// Если функция maybeThrowError выбросит исключения,
// управление сразу перейдёт в блок catch и
// сложные вычисления продолжат выполняться до
// перезагрузки страницы
maybeThrowError()
}
window.removeEventListener('scroll', expensiveCalculations)
В этом примере, если функция maybeThrowError выбросит исключение внутри блока try, управление перейдёт в блок catch. Если и в блоке catch эта функция тоже выбросит исключение, то выполнение кода прервётся, и обработчик события не будет снят, пока пользователь не перезагрузит страницу, что плохо скажется на скорости работы. Для того, чтобы избежать таких ситуаций, следует использовать блок finally:
try {
window.addEventListener('scroll', expensiveCalculations)
maybeThrowError()
} catch {
maybeThrowError()
} finally {
window.removeEventListener('scroll', expensiveCalculations)
}
Другой пример: работа с файлами. В следующем фрагменте кода показывается, как скрипт открывает файл и записывает в него какие-то данные (в серверном окружении JavaScript имеет доступ к файловой системе). Во время записи может произойти ошибка. Но после открытия файл очень важно закрыть, потому что незакрытый файл может привести к утечкам памяти. В таких случаях используется блок finally:
openMyFile();
try {
// Сделать что-то с файлом
writeMyFile(theData);
}
finally {
closeMyFile(); // Закрыть файл, что бы ни произошло
}
Примеры
Вложенные блоки try
Для начала давайте посмотрим что делает этот код:
try {
try {
throw new Error('упс');
}
finally {
console.log('finally');
}
}
catch (e) {
console.error('внешний блок catch', e.message);
}
// Вывод:
// "finally"
// "внешний блок catch" "упс"
Теперь отловим исключение во внутреннем блоке try, добавив к нему блок catch:
try {
try {
throw new Error('упс');
}
catch (e) {
console.error('внутренний блок catch', e.message);
}
finally {
console.log('finally');
}
}
catch (e) {
console.error('внешний блок catch', e.message);
}
// Output:
// "внутренний блок catch" "упс"
// "finally"
Наконец, пробросим ошибку
try {
try {
throw new Error('упс');
}
catch (e) {
console.error('внутренний блок catch', e.message);
throw e;
}
finally {
console.log('finally');
}
}
catch (e) {
console.error('внешний блок catch', e.message);
}
// Вывод:
// "внутренний блок catch" "oops"
// "finally"
// "внешний блок catch" "oops"
Любое исключение будет передано только в ближайший блок catch, если он не пробросит его дальше. Все исключения, выброшенными внутренними блоками (потому что код в блоке catch также может выбросить исключение), будут пойманы внешними.
Возвращение значения из блока finally
Если блок finally возвращает какое-либо значение, оно становится значением, которое возвращает вся конструкция try...catch...finally, вне зависимости от любых инструкций return в блоках try и catch. Также игнорируются исключения, выброшенные блоком catch.
try {
try {
throw new Error('упс');
}
catch (e) {
console.error('внутренний блок catch', e.message);
throw e;
}
finally {
console.log('finally');
return;
}
}
catch (e) {
console.error('внешний блок catch', e.message);
}
// Output:
// "внутренний блок catch" "упс"
// "finally"
«упс» не доходит до внешнего блока из-за инструкции return в блоке finally. То же самое произойдёт с любым значением, возвращаемым из блока catch.
Спецификации
| Specification |
|---|
| ECMAScript Language Specification # sec-try-statement |
Совместимость
BCD tables only load in the browser
Смотрите также
В этой статье мы познакомимся с инструкцией для обработки ошибок try...catch и throw для генерирования исключений.
Непойманные ошибки
Ошибке в коде могут возникать по разным причинам. Например, вы отправили запрос на сервер, а он дал сбой и прислал ответ, который привёл к неожиданным последствиям. Кроме этой, могут быть тысячи других, а также свои собственные.
Когда возникает ошибка, выполнение кода прекращается, и эта ошибка выводится в консоль:
const json = '{name:"Александр"}';
const person = JSON.parse(json); // Uncaught SyntaxError: Unexpected token n in JSON at position 1
console.log('Это сообщение мы не увидим!');

Выполнение этого примера остановится при парсинге строки JSON. В консоль будет выведена непойманная ошибка (uncaught error). Она так называется, потому что мы её не поймали (не обработали). Дальше код выполняться не будет и сообщение, которые мы выводим с помощью console.log() не отобразится.
Обработка ошибок в JavaScript осуществляется с помощью try...catch.
try...catch – это специальный синтаксис, состоящий из 2 блоков кода:
try {
// блок кода, в котором имеется вероятность возникновения ошибки
} catch(error) {
// этот блок выполняется только в случае возникновения ошибки в блоке try
}
Первый блок идёт сразу после ключевого слова try. В этот блок мы помещаем часть кода, в котором есть вероятность возникновения ошибки.
Второй блок располагается за ключевым словом catch. В него помещаем код, который будет выполнен только в том случае, если в первом блоке возникнет ошибка. В круглых скобках после catch указываем параметр error. В этот параметр будет помещена ошибка, которая возникла в блоке try.
Код, приведённый выше мы обернули в try...catch, а именно ту его часть, в котором может возникнуть ошибка:
const text = '{name:"Александр"}';
try {
const person = JSON.parse(text); // Uncaught SyntaxError: Unexpected token n in JSON at position 1
} catch(error) {
console.error(error);
console.log(error.message);
}
console.log('Это сообщение мы увидим!');

Здесь в блоке try произойдет ошибка, так как в данном примере мы специально присвоили переменной text некорректную строку JSON. В catch эта ошибка будет присвоена параметру error, и в нём мы будем просто выводить эту ошибку в консоль с помощью console.error(). Таким образом она будет выведена также красным цветом, но без слова Uncaught, т.к. эта ошибка была поймана.
Ошибка – это объект и у него имеются следующие свойства:
message– описание ошибки;name– тип ошибки, например, RangeError при указании значения выходящего за пределы диапазона;stack– строка стека, которая используется в целях отладки; она позволяет узнать о том, что происходило в скрипте на момент возникновения ошибки.
В этом примере мы также написали инструкцию для вывода описание ошибки error.message в консоль с помощью console.log().
Пример функции для проверки корректности JSON:
const isValidJSON = (text) => {
try {
JSON.parse(text);
return true;
} catch {
return false;
}
}

При вызове функции, сначала будет выполняться инструкция JSON.parse(text). Если ошибки не возникнет, то возвратится значение true. В противном случае, интерпретатор перейдёт в секцию catch. В итоге будет возвращено false. Кстати здесь catch записан без указания круглых скобок и параметра внутри них. Эта возможность была добавлена в язык, начиная с версии ECMAScript 2019.
Блок «finally»
В JavaScript возможны три формы инструкции try:
try...catchtry...finallytry...catch...finally
Блок finally выполняется всегда, независимо от того возникли ошибки в try или нет. Он выполняется после try, если ошибок не было, и после catch, если ошибки были. Секция finally не имеет параметров.
Пример с использованием finally:
let result = 0;
try {
result = sum(10, 20);
console.log('Это сообщение мы не увидим!');
} catch(error) {
console.log(error.message);
} finally {
console.log(result);
}

В этом примере произойдет ошибка в секции try, так как sum нигде не определена. После возникновения ошибки интерпретатор перейдём в catch. Здесь с помощью метода console.log() сообщение об ошибке будет выведено в консоль. Затем выполнится инструкция, находящаяся в блоке finally.
В JavaScript имеется также конструкция без catch:
try {
// ...
} finally {
// завершаем какие-то действия
}
Инструкция throw
В JavaScript имеется инструкция throw, которая позволяет генерировать ошибку.
Синтаксис инструкции throw:
throw expression;
Как правило, в качестве выражения обычно используют встроенный основной класс для ошибок Error или более конкретный, например: RangeError, ReferenceError, SyntaxError, TypeError, URIError или другой.
Создаём новый объект Error и выбрасываем его в качестве исключения:
throw new Error('Какое-то описание ошибки');
Пример генерирования синтаксической ошибки:
throw new SyntaxError('Описание ошибки');
В качестве выражения можно использовать не только объект ошибки, но и строки, числа, логические значения и другие величины. Но делать это не рекомендуется:
throw 'Значение не является числом';
При обнаружении оператора throw выполнение кода прекращается, и ошибка выбрасывается в консоль.
Например, создадим функцию, которая будет просто выбрасывать новую ошибку:
// создаём стрелочную функцию и присваиваем её переменной myFn
const myFn = () => {
throw new Error('Описание ошибки');
}
// вызываем функцию
myFn();
console.log('Это сообщение мы не увидим в консоли!');

Для обработки ошибки обернём вызов функции в try...catch:
const myFn = () => {
throw new Error('Описание ошибки');
}
try {
myFn();
} catch(error) {
console.error(error);
}
console.log('Это сообщение мы увидим в консоли!');

В этом примере вы увидите в консоли ошибку и дальше сообщение, которые мы выводим с помощью console.log(). То есть выполнение кода продолжится.
Кроме встроенных классов ошибок можно создать свои собственные, например, путем расширения Error:
class FormError extends Error {
constructor(message) {
super(message);
this.name = 'FormError';
}
}
Использование своего класса FormError для отображение ошибок формы:
<form novalidate>
<input type="text" name="name" required>
<input type="email" name="email" required>
<button type="submit">Отправить</button>
</form>
<script>
class FormError extends Error {
constructor(message) {
super(message);
this.name = 'FormError';
}
}
const elForm = document.querySelector('form');
elForm.onsubmit = (e) => {
e.preventDefault();
elForm.querySelectorAll('input').forEach((el) => {
if (!el.checkValidity()) {
try {
throw new FormError(`[name="${el.name}"] ${el.validationMessage}`);
} catch(error) {
console.error(`${error.name} ${error.message}`);
}
}
});
}
</script>

Глобальная ловля ошибок
Возникновение ошибок, которые мы никак не обрабатываем с помощью try, можно очень просто перехватить посредством window.onerror:
window.onerror = function(message, source, lineno, colno, error) {
// ...
}
Это анонимное функциональное выражение будет вызываться каждый раз при возникновении непойманной ошибки. Ей передаются аргументы, которые мы будем получать с помощью следующих параметров:
message— строка, содержащее сообщение об ошибке;source— URL-адрес скрипта или документа, в котором произошла ошибка;linenoиcolno— соответственно номер строки и столбца, в которой произошла ошибка;error— объект ошибки илиnull, если соответствующий объект ошибки недоступен;
Передача ошибок на сервер
Что делать с этими ошибками? Их, например, можно передавать на сервер для того чтобы позже можно было проанализировать эти ошибки и принять меры по их устранению.
Пример кода для отправки ошибок, возникающих в браузере на сервер через AJAX с использованием fetch:
window.onerror = (message, source, lineno, colno) => {
const err = { message, source, lineno, colno };
fetch('/assets/php/error-log.php', {
method: 'post',
body: JSON.stringify(err)
});
}
На сервере, если, например, сайт на PHP, можно написать такой простенький скрипт:
<?php
define('LOG_FILE', 'logs/' . date('Y-m-d') . '.log');
$json = file_get_contents('php://input');
$data = json_decode($json, true);
try {
error_log('[' . date('d.m.Y h:i:s') . '] [' . $data['message'] . '] [' . $data['lineno'] . ', ' . $data['colno'] . '] [' . $data['source'] . '] [' . $_SERVER['HTTP_USER_AGENT'] . ']' . PHP_EOL, 3, LOG_FILE);
} catch(Exception $e) {
$message = implode('; ', $data);
error_log('[' . date('d.m.Y h:i:s') . '] [' . $message . '] [' . $_SERVER['HTTP_USER_AGENT'] . ']' . PHP_EOL, 3, LOG_FILE);
}
Его следует сохранить в файл /assets/php/error-log.php, а также в этом каталоге создать папку logs для сохранения в ней логов.
В результате когда на клиенте, то есть в браузере будет возникать JavaScript ошибки, они будут сохраняться на сервер в файл следующим образом:


Сообщение было отмечено Cvetlana_tan как решение