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
34k49 gold badges179 silver badges318 bronze badges
answered May 1, 2013 at 10:59
MarioDSMarioDS
12.9k15 gold badges65 silver badges121 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?
-
Вопрос заданболее трёх лет назад
-
1204 просмотра
Вы какую ошибку пытаетесь отловить?
При 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)
}
}
-
Показать ещё
Загружается…
08 июн. 2023, в 23:22
5000 руб./за проект
08 июн. 2023, в 23:20
3000 руб./за проект
08 июн. 2023, в 23:00
15000 руб./за проект
Минуточку внимания
I have following code:-
try {
user.findOne({ Email: req.body.email }, function (e, d) {
if (d) {
res.json({
'success': false,
'json': null,
'message': 'This email already exists!',
'status': 200
});
} else {
var u = new user();
u.Email = req.body.email;
u.Password = req.body.password;
u.Name = req.body.name;
user.save(function (e, d) {
res.json(d);
});
}
});
} catch (ex) {
console.log(ex.message + " n" + ex.stack);
res.json({
'success': false,
'json': ex,
'message': 'Opps! something wen wrong please try again later!',
'status': 500
});
}
}
I have an exception on line user.save(function (e, d) {
I solve the issue but the problem is I see catch block doesn’t fire at all and node server stop due to exception. if I put try block inside user.findOne
catch block will be fire can anyone please explain me why this behavior in node application?
Thanks you!
asked Sep 25, 2015 at 12:03
7
findOne method is asyn process so your try catch statement will not catch the exception which has occurred within Call Back method. You have to put your try catch statement within call back method to catch the exception.
user.findOne({
Email: req.body.email
}, function(e, d) {
try {
if (d) {
res.json({
'success': false,
'json': null,
'message': 'This email already exists!',
'status': 200
});
} else {
var u = new user();
u.Email = req.body.email;
u.Password = req.body.password;
u.Name = req.body.name;
user.save(function(e, d) {
res.json(d);
});
}
} catch (ex) {
console.log(ex.message + " n" + ex.stack);
res.json({
'success': false,
'json': ex,
'message': 'Opps! something wen wrong please try again later!',
'status': 500
});
}
}););
answered Sep 25, 2015 at 12:20
Bala.RajBala.Raj
9918 silver badges18 bronze badges
Я пишу приложение на node.js/express/mongoDB, если кратко описать суть, то сейчас я создаю функцию которая генерирует токен, с помощью которого можно будет проверять почту пользователя. Вот проблемный код:
Caller.js:
/*
Функция сreateToken() возвращает обьект: err - в слушае ошибки (error message),
data - в случае успеха (true), status - в случае ошибки (500, 404...).
*/
try{
let {err, data, status} = await createToken(userID);
if(err) callback(err, null, status); // Передаем информацию об ошибке дальше
else callback(null, true); // Всё хорошо, нет ошибок, передаем информацию дальше
}catch(err){
console.log(err);
}
createToken.js
async function createToken(user_id){
try{
let newToken = new Tokens({ // Создаем обьект токена
user_id: user_id,
token_id: generateSomeId() // Генерируем id для токена
});
await newToken.save(); // Cохраняем созданный токен в базу данных
return {err: null, data: true};// Если всё хорошо, возвращаем обьект с пустой ошибкой.
}catch(err){
if(err && err.code == 11000){ //Если токен с таким id уже существует
createToken(user_id); //Вызываем эту же функцию ещё раз (рукурсия), чтобы сгенерировать другой id
}else{
return {err: 'Something went wrong', data: null, status: 500}
/*Если ошибка другая, возвращаем сообщение об неизвестной ошибке*/
}
}
}
Что данный код должен делать
Для генерации уникальных id
для токена я использую uuid4
— он достаточно безопасный, и уникальный, поэтому вероятность возникновения двух идентичных id
очень мала. Но даже учитывая это, я сделал обработку такой ошибки — (Если вдруг токен с таким id уже существует) теперь если такой токен уже есть в базе данных, мы вызываем эту же функцию (createToken()
) ещё раз, тем самым, сгенерируется новый id
токена.
В этом примере вместо uuid4
я использую свою функию для генерации id — generateSomeId()
, эта функция имеет только два уникальных значения: [‘a’, ‘b’] — Функция рандомно возвращает значение из этого массива, тоесть может быть только два уникальных токена, если эти два уникальных токена созданы, и мы попытаемся создать третий токен, то мы постоянно будем попадать в блок catch(err)
в блок, который вызывает сам себя, тем самым, эта функция будет вызывать себя бесконечно.
Что на самом деле он делает
Так и происходит, но так же есть и ошибка, причину которой я не могу найти:
При создании первого токена всё идёт хорошо, токен создается с id: 'a'
(например) и сохраняется в базе данных. При создании 2-го токена, если сгенерируется другой id, допустим id: 'b'
— тоже всё хорошо, но если сгенерируется токен с id который уже существует в базе данных, то выполнится блок catch(err)
, блок где вызывается рекурсия (там где мы вызываем функцию createToken()
), за тем эта функция опять выполнится сначала, и когда доходит до строки с await newToken.save();
то я получаю ошибку:
TypeError: Cannot destructure property 'err' of '(intermediate value)' as it is undefined.
Эта ошибка возникает в модуле который вызывает функцию createToken()
, то есть в Caller.js
, в блоке catch(err)
. Эта ошибка говорит что в возвращаемом обьекте из createToken()
, свойство err
равно undefined
, как и в свойстве data
и status
.
Вопрос
Я не знаю почему так происходит? Почему при вызове рекурсии createToken()
я получаю эту ошибку, которая говорит что свойства возвращаемого обьекта равны undefined
? Разве ошибку не должен поймать блок catch(err)
в функции createToken()
? Как я могу решить данную проблему? Целый день ищу причину но безрезультатно. Буду очень благодарен если кто-то понимает в чем может быть ошибка. Заранее Благодарю !)
В этой статье мы познакомимся с инструкцией для обработки ошибок 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()
не отобразится.
try…catch
Обработка ошибок в 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...catch
try...finally
try...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 ошибки, они будут сохраняться на сервер в файл следующим образом: