I have a suspicion that I'm using the finally block incorrectly, and that I don't understand the fundamentals of its purpose...
function myFunc() {
try {
if (true) {
throw "An error";
}
} catch (e) {
alert (e);
return false;
} finally {
return true;
}
}
This function will run the catch block, alert "An error", but then return true. Why doesn't it return false?
The finally block contains statements to execute after the try and catch blocks execute but before the statements following the try...catch statement. The finally block executes whether or not an exception is thrown. If an exception is thrown, the statements in the finally block execute even if no catch block handles the exception. more
The finally block will always run, try returning true after your try block
function myFunc() {
try {
if (true) {
throw "An error";
}
return true;
} catch (e) {
alert (e);
return false;
} finally {
//do cleanup, etc here
}
}
Finally blocks execute when you leave the try block. In your code this happens when you return false. That sets the return value to false and attempts to exit the function. But first it has to exit the try block which triggers the finally and overwrites the return value to true.
It is considered by many to be a good programming practice to have a single return statement per function. Consider making a var retval at the beginning of your function and setting it to true or false as appropriate throughout your function and then structuring the code so that it falls correctly through to a single return at the bottom.
function getTheFinallyBlockPoint(someValue) {
var result;
try {
if (someValue === 1) {
throw new Error("Don't you know that '1' is not an option here?");
}
result = someValue
} catch (e) {
console.log(e.toString());
throw e;
} finally {
console.log("I'll write this no matter what!!!");
}
return result;
};
getTheFinallyBlockPoint("I wrote this only because 'someValue' was not 1!!!");
getTheFinallyBlockPoint(1);
Run this on your browser's console and it might give you the answer you're looking for.
Related
This may be an elementary question, but it is breaking my brain.
I have a structure like this in NodeJS (typescript):
while(true) {
if (something) {
code...
try{
dangerousCode();
}catch(e){
console.log(e);
//Now I want to exit from this if statement and go to the next one
}
some other code...
}
if (somethingElse) ...
}
How can I leave a catch statement like that and go to the next if (so I need to currently leave the if statement where the catch block is). Should I use break or continue keyword? Should I do something else?
try something like this
while(true) {
if (something) {
code...
try{
dangerousCode();
some other code...
}catch(e){
console.log(e);
// Now you will exit this if block, as there are no more instructions
}
}
if (somethingElse) ...
}
If an exception is thrown, it will get caught and handled in the catch block and then directly go the next if statement.
If no exception occurs, the dangerousCode() will execute normally and pass to some other code... after it.
You will have to add another variable and a condition in this case.
let enterFirstIfBlock = true;
while(true) {
if (enterFirstIfBlock && something) {
code...
try{
dangerousCode();
} catch(e) {
console.log(e);
enterFirstIfBlock = false;
}
if (enterFirstIfBlock) {
some other code...
}
}
if (somethingElse) ...
}
while(true) {
if (something) {
code...
try{
dangerousCode();
}catch(e){
console.log(e);
//Now I want to exit from this if statement and go to the next one
}
some other code...
}
if (somethingElse) ...
}
I suggest you move your second if statement to a function say doSomething(), and then call this function within your catch block, and after first if, like this:
while(true) {
if (something) {
code...
try{
dangerousCode();
}catch(e){
console.log(e);
doSomething();
continue;
//Now I want to exit from this if statement and go to the next one
}
some other code...
}
doSomething();
}
function doSomething() {
if (somethingElse) ...
}
You will need to pass appropriate params, and handle them accordingly, and also add continue in after doSomething in catch if nothing else is required.
An esoteric, but occasionally convenient feature is using a label with a block scope.
label
The labeled statement can be used with break or continue statements. It is prefixing a statement with an identifier which you can refer to.
It allows you to break out of a code block by its label name and continue execution after the end of the block. Here's a contrived example to demonstrate how to use it. (Of course, see the linked documentation as well.)
function fork () {
return Math.random() < 0.5;
}
function getValue () {
const useFirst = fork();
if (fork()) return useFirst ? 'a' : 'b';
return useFirst ? 1 : 2;
}
while (true) {
let value = getValue();
stringCheck:
if (typeof value === 'string') {
// code...
try{
if (fork()) throw new Error('Bad luck');
}
catch (ex) {
console.error(ex);
break stringCheck; // Breaks out of the block associated with the label
}
// some other code...
}
value = getValue();
numberCheck:
if (typeof value === 'number') {
console.log('Got a number');
// break numberCheck; // If uncommented, would break out of this block
break; // Break out of the while loop
}
}
This question already has answers here:
Uses of the finally statement
(9 answers)
Closed 1 year ago.
This question may appear similar to others that have been answered, but I can't find an answer relating to JavaScript.
What is the difference between code in a finally block and code that comes after the entire try ... catch ... finally statement?
That is, what is the difference between this code:
try {
f(x);
}
catch(e) {
g(e);
}
finally {
h(y);
}
and this code:
try {
f(x);
}
catch(e) {
g(e);
}
h(y);
One difference is that, if a value is returned in a finally, it will override values returned from inside the prior try and catch blocks:
function foo() {
try {
throw new Error('1');
} catch(e) {
return '2';
} finally {
return '3';
}
}
console.log(foo());
Returning from a finally will also prevent throws in a try or catch from percolating outward - instead, only the finally's normal return completion value will be the result.
(function() {
try {
try {
throw new Error('oops');
} catch (ex) {
console.error('inner', ex.message);
throw ex;
} finally {
console.log('finally');
return;
}
} catch (ex) {
// not entered into
console.error('outer', ex.message);
}
})();
I'll admit this question had me scratching my head at first. But a look at the MDN reference for try...catch includes this salient section on "Returning from a finally-block". It appears that if you return from a finally block, it will override anything returned or thrown from the preceding try or catch blocks. So while your example may be identical, if you were to change it to this:
try {
return f(x);
}
catch(e) {
throw g(e);
}
finally {
return h(y);
}
...it would fundamentally differ from this:
try {
return f(x);
}
catch(e) {
throw g(e);
}
return h(y);
I have the following switch statement in several places in my code:
try {
...
} catch(e) {
switch(x){
case A:
throw e;
default:
return e;
}
}
I would love to be able to wrap it in a function like this:
function handle(e) {
switch(x) {
case A:
throw e;
default:
return e;
}
}
try {
...
} catch(e) {
handle(e);
}
I know the above case doesn't work (the code executing "handle" still doesn't throw or return anything) but it would be really nice to make the code a little more DRY.
Generally speaking, this shouldn't be a problem. Your example is a bit generic (e. g.: What is A and x? Do they need to be passed or can you derive them from the error?), so this example provides a general "solution" as well which (hopefully) suits your needs.
You could consider creating a "error-case" handler for various types of errors. The handler only every throws the error, if it cannot find a defined error case.
// Higher-order function to create "error handlers":
function handleBy (cases) {
return function (err) {
if (cases[err.constructor.name]) {
return cases[err.constructor.name](err);
}
throw err;
}
}
// create an error handler which returns different "defaults" or "fallbacks"
// for certain types of errors. alternatively, it returns the error itself
var handleRead = handleBy({
TypeError: function (err) {
return 'default value';
},
SyntaxError: function (err) {
return err;
}
});
// this is the action to be guarded
var unsafeAction = function () {
try {
return window.foo.bar;
} catch (e) {
return handleRead(e);
}
}
console.log(unsafeAction())
I'm trying to create a function that's responsible for checking a boolean and exiting early with a warning, if true.
Here's example of what i'm trying to achieve:
function warnAndDie(shouldDie) {
if(shouldDie) {
console.log("go away, i'm dying!");
// TODO: some code to cause the calling function to exit early
}
}
function triggerTheWarnAndDie() {
shouldWarnAndDie(true);
console.log("I should never run!");
}
function dontTriggerTheWarnAndDie() {
shouldWarnAndDie(false);
console.log("I should run!");
}
What can i do so that warnAndDie is able to cause the calling functions to terminate early?
thank you
You have several options. I'll list the two very basic ones for you:
Return a value (probably boolean) and return early from you caller depending on the initial return value
function shouldWarnAndDie(shouldDie) {
if(shouldDie) {
console.log("go away, i'm dying!");
return true;
}
return false;
}
function triggerTheWarnAndDie() {
var hasDied = shouldWarnAndDie(true);
if (hasDied) return;
console.log("I should never run!");
}
Throw an exception
function shouldWarnAndDie(shouldDie) {
if(shouldDie) {
throw "Go away, i'm dying!";
// or cleaner:
// throw new dyingException("Go away, i'm dying!");
}
}
function triggerTheWarnAndDie() {
try {
shouldWarnAndDie(true);
console.log("I should never run!");
}
catch(err) {
console.log(err+" He's dead Jim!");
}
}
There are more advance mechanics which are probably out of scope for you right now, but LINQ's nice answer about callbacks and promises is definitely worth a look.
This can be achieved with basic exception handling. Here I have created a custom exception which can be caught using a try catch statement.
function shouldWarnAndDie(shouldDie) {
if(shouldDie) {
throw new DyingException();
}
}
function triggerTheWarnAndDie() {
try {
shouldWarnAndDie(true);
} catch(err) {
console.log(err.message);
return;
}
console.log("I should never run!");
}
function dontTriggerTheWarnAndDie() {
try {
shouldWarnAndDie(false);
} catch(err) {
console.log(err.message);
return;
}
console.log("I should run!");
}
// custom Exception handler
function DyingException() {
// do some custom exception handling here
return new Error("Go away, I am dying!");
}
triggerTheWarnAndDie(); // Go away, I am dying!
dontTriggerTheWarnAndDie(); // I should run!
Here is a JsFiddle Example
use the
return;
keyword to exit
*This is just a quick workaround. You may want to look into error checking and exceptions...
I'd suggest using promises but its not supported natively in all browsers. We can use callbacks where the code inside the callback only gets executed when warnAndDie allows it to execute.
function warnAndDie(shouldDie, fn) {
if(shouldDie) {
console.log("go away, i'm dying!");
// TODO: some code to cause the calling function to exit early
return;
}
fn();
}
function triggerTheWarnAndDie() {
shouldWarnAndDie(true, function () {
console.log("I should never run!");
} );
}
function dontTriggerTheWarnAndDie() {
shouldWarnAndDie(false, function () {
console.log("I should run!");
} );
}
I have tried this code in javascript
function abc(){
try{
console.log(0);
throw "is empty";}
catch(err){
console.log(1);
return true;
}
finally{return false;}
return(4);
}
console.log(abc());
I got output as false. I understand Finally always execute regardless of result of try catch but what happen to return statement in catch .
I understand Finally always execute regardless of result of try catch
but what happen to return statement in catch .
Return statement in catch will be executed only if the catch block is reached, i.e. if there is an error thrown.
For example
function example() {
try {
throw new Error()
return 1;
}
catch(e) {
return 2;
}
finally {
}
}
example() will return 2 since an error was thrown before return 1.
But if there is a finally block and this finally block has a return statement then this return will override catch return statement.
For example
function example() {
try {
throw new Error()
return 1;
}
catch(e) {
return 2;
}
finally {
return 3;
}
}
Now example() will return 3.
In your example, there is a return statement after the finally block. That statement will never get executed.
Try
function example() {
try {
throw new Error()
return 1;
}
catch(e) {
return 2;
}
finally {
return 3;
}
console.log(5)
return 4;
}
It only outputs 3. 5 is never printed since after finally block value is returned.
Finally its always executed the last. So it overrides any other return you have. Therefore, your method returns false