Javascript try... catch... else... наконец, как Python, Java, Ruby и т.д.
Как Javascript может дублировать четырехуровневую модель исполнения try
- catch
- else
- finally
, поддерживаемую другими языками?
Ясное краткое резюме из Python 2.5, что нового. В условиях Javascript:
// XXX THIS EXAMPLE IS A SYNTAX ERROR
try {
// Protected-block
} catch(e) {
// Handler-block
} else {
// Else-block
} finally {
// Final-block
}
Выполняется код в Защищенном блоке. Если код генерирует исключение, выполняется Обработчик-блок; Если исключение не выбрано, выполняется Else-block.
Независимо от того, что произошло ранее, Final-block выполняется, как только блок кода завершен, и обрабатываются любые обработанные исключения. Даже если возникает ошибка в Обработчике-блоке или Else-block и возникает новое исключение, код в Конечный блок все еще запущен.
Обратите внимание, что сокращение Else-block и вставка в конце Защищенного блока неверно. Если ошибка произошла в Else-block, ее нельзя обрабатывать Обработчик-блок.
Ответы
Ответ 1
Немного расширяя идею jhs, вся концепция может быть помещена внутри функции, чтобы обеспечить еще большую читаемость:
var try_catch_else_finally = function(protected_code, handler_code, else_code, finally_code) {
try {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
} finally {
finally_code();
}
};
Затем мы можем использовать его так (очень похоже на путь python):
try_catch_else_finally(function() {
// protected block
}, function() {
// handler block
}, function() {
// else block
}, function() {
// final-block
});
Ответ 2
Я знаю, что это старое, но вот чисто синтаксическое решение, которое я считаю правильным:
try {
// Protected-block
try {
// Else-block
} catch (e) {
// Else-handler-block
}
} catch(e) {
// Handler-block
} finally {
// Final-block
}
Код в Защищенном блоке выполняется. Если код выдает ошибку, выполняется блок обработчика; Если ошибка не выдана, Else-block выполняется.
Независимо от того, что произошло ранее, Final-block выполняется после завершения блока кода и обработки любых сгенерированных ошибок. Даже если есть ошибка в блоке обработчика или блоке Else, код в блоке Final все еще выполняется.
Если в блоке Else выдается ошибка, она обрабатывается не блоком Handler, а блоком Else-handler
А если знаешь, что Else-блок не кинет
try {
// Protected-block
// Else-block
} catch(e) {
// Handler-block
} finally {
// Final-block
}
Мораль истории, не бойся отступать;)
Примечание: это работает, только если блок Else-handler- никогда не выбрасывает.
Ответ 3
Javascript не имеет синтаксиса для поддержки сценария без исключения. Лучшим обходным решением является вложенный оператор try
, похожий на "устаревший" метод из PEP 341
// A pretty-good try/catch/else/finally implementation.
try {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
} finally {
this_always_runs();
}
Помимо читаемости, единственной проблемой является переменная success
. Если protected_code
устанавливает window.success = false
, это не сработает. Менее читаемый, но безопасный способ использует пространство имен функций:
// A try/catch/else/finally implementation without changing variable bindings.
try {
(function() {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
})();
} finally {
this_always_runs();
}
Ответ 4
Я знаю, что вопрос старый, и ответы уже даны, но я думаю, что мой ответ является самым простым, чтобы получить "else" в блоке try-catch javascripts.
var error = null;
try {
/*Protected-block*/
} catch ( catchedError ) {
error = catchedError; //necessary to make it available in finally-block
} finally {
if ( error ) {
/*Handler-block*/
/*e.g. console.log( 'error: ' + error.message );*/
} else {
/*Else-block*/
}
/*Final-block*/
}
Ответ 5
Здесь другое решение, если проблема является общей: нежелание вызова обратного вызова с ошибкой при возникновении неперехваченной ошибки, выданной первым обратным вызовом.... т.е. концептуально вы хотите...
try {
//do block
cb(null, result);
} catch(err) {
// err report
cb(err)
}
Но ошибка в успехе cb вызывает проблему вызова cb во второй раз. Поэтому вместо этого я начал использовать
try {
//do block
try {
cb(null, result);
} catch(err) {
// report uncaught error
}
} catch(err) {
// err report
cb(err)
}
который является вариантом решения @cbarrick.