Try с catch: try…catch — JavaScript | MDN
Содержание
C++ | Вложенные try-catch
Последнее обновление: 17.03.2023
Одни конструкции try-catch
могут содержать другие. Если исключение возникает во вложенной конструкции try-catch, то программа сначала ищет во вложенной конструкции
блок catch, который обрабатывает нужный тип исключения. Если во вложенной конструкции try-catch такой блок catch не найден, то программа начинает искать аналогичный блок catch во внешей
конструкии try-catch. Посмотрим на примере.
#include <iostream> double divide(int a, int b) { if(!b) // если b == 0 { throw "Division by zero"; } return a / b; } int main() { try { try { int a{10}, b{}; double result {divide(a, b)}; std::cout << result << std::endl; } catch (const char* error) { std::cout << "Inner execption: " << error << std::endl; } std::cout << "Inner try-catch finished" << std::endl; } catch (const char* error) { std::cout << "External execption: " << error << std::endl; } std::cout << "External try-catch finished" << std::endl; }
Здесь функция divide()
вызывается во внутренней конструкции try-catch. Оператор throw генерирует исключение, объект которого представляет строковый литерал — тип
const char*
.
Во вложенной конструкции try-catch есть такой блок catch, который обрабатывает исключения типа const chat*
. И выполнения этого блока catch программа продолжает свой
обычный ход работы, а блок catch во внешей конструкции try-catch НЕ выполняется. В итоге будет следующий консольный вывод:
Inner execption: Division by zero Inner try-catch finished External try-catch finished
Теперь возьмем другую ситуацию — во вложенной конструкции try-catch нет нужного блока catch:
#include <iostream> double divide(int a, int b) { if(!b) // если b == 0 { throw "Division by zero"; } return a / b; } int main() { try { try { int a{10}, b{}; double result {divide(a, b)}; std::cout << result << std::endl; } catch (unsigned error) { std::cout << "Inner execption: " << error << std::endl; } std::cout << "Inner try-catch finished" << std::endl; // эта строка не выполняется } catch (const char* error) { std::cout << "External execption: " << error << std::endl; } std::cout << "External try-catch finished" << std::endl; }
Фактически это тот же самый пример, только теперь блок catch во вложенной конструкции обрабатывает исключения типа unsigned
. В итоге, когда будет сгенерировано исключение,
вложенная конструкция не сможет найти нужный блок catch для обработки исключения типа const char*
. Поэтому выполнение выполнение программы переходит в блок
catch внешней конструкции try-catch
, который обрабатывает исключения типа const char*
. Поэтому консольный вывод будет другим
External execption: Division by zero External try-catch finished
НазадСодержаниеВперед
try…catch — JavaScript — Дока
Кратко
Скопировано
Конструкция try
позволяет выполнить произвольный код, но если в нем произошла ошибка, то программа не остановит своё выполнение, а перейдёт в блок catch
, где ошибку можно обработать.
Как понять
Скопировано
Ошибки в программах это очень неприятно, но никто не застрахован от их появления. К тому же, ошибки могут появляться в тех ситуациях, которые не зависят от нас самих. Например, пользователь неправильно воспользовался программой. Поэтому в языке необходимы конструкции, которые позволяют выполнить произвольный код, но в случае ошибки дать возможность её обработать.
В JavaScript ситуация ещё сложнее. Если во время работы скрипта возникла ошибка и она не была обработана, то выполнение останавливается, и программа больше не работает.
Конструкция try
делает программы стабильнее — в случае ошибки мы можем продолжить выполнение. Мы можем написать любой синтаксически верный код и, если он выполнится без ошибок, то отлично. Если же что-то пойдёт не так, то выполнится код, написанный в catch
.
Представьте, что вы тренируетесь отбивать мяч в бейсбол. У вас есть партнёр, который будет ловить мяч, в случае вашей ошибки, если отбить мяч не удастся. В большинстве попыток у вас все будет получаться хорошо, но если же случится промах, то второй игрок поймает мяч и вернёт его на место, чтобы можно было попробовать снова.
С пойманной в catch
ошибкой можно поступить как угодно: отправить данные в специальный логгер, обработать данные из неё и даже выбросить новую ошибку, которая может быть поймана в другом месте и т.д.
Как пишется
Скопировано
Базовый случай
Скопировано
Чтобы использовать try
, необходимо в блоке try
написать код, который нужно исполнить, а в блоке catch
написать, что делать в случае ошибки.
try { someFunction() anotherFunction()} catch (err) { console.log('Поймали ошибку! Вот она: ', err.message)}
try {
someFunction()
anotherFunction()
} catch (err) {
console.log('Поймали ошибку! Вот она: ', err.message)
}
Если в блоке try
не произошло ошибок, то код в блоке catch
не выполнится.
Важно помнить, что код в try
должен быть синтаксически верным. Если написать невалидный код (например, не закрыть фигурные скобки), то скрипт не запустится, потому что JavaScript не поймёт код. Ошибки, которые обработает блок
catch
, будут ошибками во время выполнения программы.
В случае ошибки выполнение в блоке try
прерывается и сразу же переходит в блок catch
. После него скрипт продолжит своё выполнение, как и прежде.
try { const six = 6 // 1. Создаём константу console.log(six) // 2. Выведет 6 six = 7 // Ошибка! Присваиваем новое значение в const // с этого места управление переходит в catch const nine = 9 // не выполнится console.log(six + nine) // и это тоже не исполнится} catch (err) { console.log('Поймали ошибку!') // 3. Обработали ошибку}console.log('Что ж, можно и продолжать') // 4. Будет выполняться дальше
try {
const six = 6 // 1. Создаём константу
console.log(six) // 2. Выведет 6
six = 7 // Ошибка! Присваиваем новое значение в const
// с этого места управление переходит в catch
const nine = 9 // не выполнится
console.
log(six + nine) // и это тоже не исполнится
} catch (err) {
console.log('Поймали ошибку!') // 3. Обработали ошибку
}
console.log('Что ж, можно и продолжать') // 4. Будет выполняться дальше
finally
Скопировано
Рассмотрим ситуацию, когда в случае успеха или неудачи выполнения какого-то участка кода нам необходимо проводить какие-то действия, чтобы корректно завершить работу скрипта.
try { // подключаемся к вебсокету, но в конце нужно обязательно отключиться webSocket.connect('ws://....') callMayThrowError()} catch (err) { ...}// Пробуем отключаться после try...catchwebSocket.disconnect('ws://....')
try {
// подключаемся к вебсокету, но в конце нужно обязательно отключиться
webSocket.connect('ws://....')
callMayThrowError()
} catch (err) {
...
}
// Пробуем отключаться после try...catch
webSocket.disconnect('ws://....')
Казалось бы никаких проблем с этим кодом быть не должно, ведь неважно выполнится код в блоке try
правильно или попадёт в catch
, следующая строчка должна выполниться. Однако возможна ситуация, что в блоке
catch
тоже возникнет ошибка, и тогда выполнение следующей строчки уже не случится.
function doSomeWithError(e) { throw new Error('new error')}try { // подключаемся к вебсокету, но в конце нужно обязательно отключиться webSocket.connect('ws://....') callMayThrowError()} catch (err) { // Здесь тоже может возникнуть ошибка doSomeWithError(err)}// В случае ошибки эта строчка уже не выполнитсяwebSocket.disconnect('ws://....')
function doSomeWithError(e) {
throw new Error('new error')
}
try {
// подключаемся к вебсокету, но в конце нужно обязательно отключиться
webSocket.connect('ws://....')
callMayThrowError()
} catch (err) {
// Здесь тоже может возникнуть ошибка
doSomeWithError(err)
}
// В случае ошибки эта строчка уже не выполнится
webSocket.disconnect('ws://....')
Как же тогда гарантированно освободить ресурсы при любом исходе выполнения?
В конструкцию try
можно добавить блок
finally
, который выполнится после блоков try
и catch
. Неважно какой код выполнился в предыдущих блоках, после их завершения (даже если из catch
была выброшена новая ошибка) исполнится код в блоке finally
.
try { webSocket.connect('ws://....') callMayThrowError()} catch (err) { // Здесь тоже может возникнуть ошибка doSomeWithError(err)} finally { // Выполнится всегда webSocket.disconnect('ws://....')}
try {
webSocket.connect('ws://....')
callMayThrowError()
} catch (err) {
// Здесь тоже может возникнуть ошибка
doSomeWithError(err)
} finally {
// Выполнится всегда
webSocket.disconnect('ws://....')
}
Наличие блока finally
необязательно. finally
можно использовать и без блока catch
.
try { // Отправить данные на сервер, здесь нам неважна обработка ошибки sendData()} finally { // Закрыть соединение при любом результате closeConnection()}
try {
// Отправить данные на сервер, здесь нам неважна обработка ошибки
sendData()
} finally {
// Закрыть соединение при любом результате
closeConnection()
}
Ошибки в catch
Скопировано
Может возникнуть ситуация, когда скрипт обработки ошибки тоже может сломаться. При этом могут возникнуть случаи, когда мы хотим намеренно выбросить новую ошибку из
catch
, или пробросить текущую, чтобы её обработать в другом месте.
Хорошей практикой считается обрабатывать в модуле только те ошибки, которые связаны непосредственно с ним, а все остальные пробрасывать дальше.
// parse-module.js// Есть свой тип ошибкиclass ParsingError extends Error { ...}function parse(data) { try { parseData(data) } catch (err) { if (err.name !== 'ParsingError') { // Другой тип ошибок пробрасываем дальше throw err } logError(err)}}
// parse-module.js
// Есть свой тип ошибки
class ParsingError extends Error {
...
}
function parse(data) {
try {
parseData(data)
} catch (err) {
if (err.name !== 'ParsingError') {
// Другой тип ошибок пробрасываем дальше
throw err
}
logError(err)
}
}
Таким образом, можно разделить ответственность, а обработкой проброшенной ошибки займётся внешний catch.
import parse from 'parse-module'try { parse(data)} catch (e) { console.log('Неизвестная ошибка парсинга:', e)}
import parse from 'parse-module'
try {
parse(data)
} catch (e) {
console.log('Неизвестная ошибка парсинга:', e)
}
Ошибки в асинхронном коде
Скопировано
Конструкция try
работает только синхронно. Таким образом, с помощью try
нельзя обработать ошибку, которая возникла в асинхронном коде.
try { // Код выполнится корректно, т.к. отсюда вернулся промис Promise.reject('err')} catch (e) { // Ошибка не будет поймана console.log('Ошибка', e)}try { // Здесь также код выполнится корректно, потому что установил таймаут без ошибок setTimeout(() => { throw Error('ошибка') }, 1000)} catch (e) { // Ошибка из таймаута также сюда не попадёт console.log('Ошибка', e)}
try { // Код выполнится корректно, т.к. отсюда вернулся промис Promise.reject('err') } catch (e) { // Ошибка не будет поймана console.log('Ошибка', e) } try { // Здесь также код выполнится корректно, потому что установил таймаут без ошибок setTimeout(() => { throw Error('ошибка') }, 1000) } catch (e) { // Ошибка из таймаута также сюда не попадёт console.log('Ошибка', e) }
Однако, если записать асинхронный код в синхронном стиле с помощью async/await, то в этом случае обработку ошибок можно осуществлять с помощью try
.
async function handlePromise() { try { // Промис вернется с ошибкой await Promise.reject('err') } catch (e) { // Теперь ошибка будет поймана console.log('Ошибка', e) // err }}handlePromise()
async function handlePromise() {
try {
// Промис вернется с ошибкой
await Promise.
reject('err')
} catch (e) {
// Теперь ошибка будет поймана
console.log('Ошибка', e) // err
}
}
handlePromise()
Чтобы поймать ошибку из set
, блоки try
должны находиться внутри функции.
На практике
Скопировано
Егор Огарков советует
Скопировано
Любой асинхронный код можно переписать в синхронном стиле через async
, чтобы использовать единый стиль обработки ошибок, используя try
. Например, перепишем установку таймаута из примера выше:
function wait(ms) { return new Promise((resolve) => setTimeout(resolve, ms))}async function timeout(fn, ms) { try { // Ждем таймаут await wait(ms) // И выполняем функцию fn() } catch (err) { // Ловим ошибку console.log('Ошибка', err) }}
function wait(ms) { return new Promise((resolve) => setTimeout(resolve, ms)) } async function timeout(fn, ms) { try { // Ждем таймаут await wait(ms) // И выполняем функцию fn() } catch (err) { // Ловим ошибку console.log('Ошибка', err) } }
Теперь можно вызывать функцию как прежде, ошибка будет поймана.
timeout(() => { throw Error('ошибка')}, 1000)
timeout(() => {
throw Error('ошибка')
}, 1000)
Документация JDK 20 — Главная
- Главная
- Ява
- Java SE
- 20
Обзор
- Прочтите меня
- Примечания к выпуску
- Что нового
- Руководство по миграции
- Загрузить JDK
- Руководство по установке
- Формат строки версии
Инструменты
- Технические характеристики инструментов JDK
- Руководство пользователя JShell
- Руководство по JavaDoc
- Руководство пользователя средства упаковки
Язык и библиотеки
- Обновления языка
- Основные библиотеки
- HTTP-клиент JDK
- Учебники по Java
- Модульный JDK
- Руководство программиста API бортового регистратора
- Руководство по интернационализации
Технические характеристики
- Документация API
- Язык и ВМ
- Имена стандартных алгоритмов безопасности Java
- банок
- Собственный интерфейс Java (JNI)
- Инструментальный интерфейс JVM (JVM TI)
- Сериализация
- Проводной протокол отладки Java (JDWP)
- Спецификация комментариев к документации для стандартного доклета
- Прочие характеристики
Безопасность
- Руководство по безопасному кодированию
- Руководство по безопасности
Виртуальная машина HotSpot
- Руководство по виртуальной машине Java
- Настройка сборки мусора
Управление и устранение неполадок
- Руководство по устранению неполадок
- Руководство по мониторингу и управлению
- Руководство по JMX
Client Technologies
- Руководство по специальным возможностям Java
Исключения | Документация Kotlin
Классы исключений
Все классы исключений в Kotlin наследуют класс Throwable
. Каждое исключение имеет сообщение, трассировку стека и необязательную причину.
Чтобы создать объект исключения, используйте выражение throw
:
fun main() {
// начало выборки
выбросить исключение(«Привет!»)
//конец выборки
}
Чтобы перехватить исключение, используйте выражение try
… catch
:
try {
// какой-то код
} поймать (e: SomeException) {
// обработчик
} окончательно {
// необязательный блок finally
}
Блоков catch
может быть ноль или более, а блок finally
может быть опущен. Однако требуется хотя бы один блок catch
или finally
.
Try — это выражение
try
— это выражение, что означает, что оно может иметь возвращаемое значение:
значение a: Внутр.? = try { input.toInt() } catch (e: NumberFormatException) { null }
Возвращаемое значение выражения try
является либо последним выражением в блоке try
, либо последним выражением в блоке catch
(или блоки). Содержимое блока
finally
не влияет на результат выражения.
Проверенные исключения
В Kotlin нет проверенных исключений. Для этого есть много причин, но мы приведем простой пример, иллюстрирующий, почему это так.
Ниже приведен пример интерфейса из JDK, реализованного классом StringBuilder :
Appendable append(CharSequence csq) выдает IOException;
Эта подпись говорит о том, что каждый раз, когда я добавляю строку к чему-то ( StringBuilder
, какому-то журналу, консоли и т. д.), я должен перехватывать IOExceptions
. Почему? Поскольку реализация может выполнять операции ввода-вывода ( Writer
также реализует Appendable
). В результате повсюду появляется такой код:
try {
log.append(сообщение)
} поймать (IOException e) {
// Должен быть безопасным
}
И это нехорошо. Просто взгляните на Effective Java, 3rd Edition, Item 77: Не игнорируйте исключения .
Брюс Экель говорит о проверенных исключениях следующее:
И вот некоторые дополнительные мысли по этому поводу:
Проверенные исключения Java были ошибкой (Род Вальдхофф)
Проблема с проверенными исключениями (Андерс Хейлсберг)
Если вы хотите предупредить вызывающих абонентов о возможных исключениях при вызове кода Kotlin из Java, Swift или Objective-C, вы можете использовать аннотацию @Throws
. Узнайте больше об использовании этой аннотации для Java, Swift и Objective-C.
Тип Nothing
throw
— это выражение в Kotlin, поэтому вы можете использовать его, например, как часть выражения Элвиса:
val s = person.name ?: throw IllegalArgumentException(«Name required»)
Выражение throw
имеет тип Nothing
. Этот тип не имеет значений и используется для обозначения местоположений кода, которые никогда не могут быть достигнуты.