Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to assign value in a try block

let x;
try {
  x = ...;
} catch (e) { 
  return
}

// rest of the code that uses `x`
const y = x + ...;

x is assigned exactly once, yet I have to use let instead of const.

The other way would be:

try {
  const x = ...;
  // rest of the code that uses `x`
  const y = x + ...;
} catch (e) { 
  return
}

However, this increases nesting and makes it unclear what can throw an error.

Is there a better way?

I don't have to care about the value of x if the try fails, as I'll be returning in the catch block.
I also don't want to extract it out to separate functions.

like image 756
Avery235 Avatar asked May 12 '18 09:05

Avery235


People also ask

How to handle error in try catch block?

Place any code statements that might raise or throw an exception in a try block, and place statements used to handle the exception or exceptions in one or more catch blocks below the try block. Each catch block includes the exception type and can contain additional statements needed to handle that exception type.

Can we use try catch in catch block?

Yes, we can declare a try-catch block within another try-catch block, this is called nested try-catch block.

What are try catch statements?

The try statement allows you to define a block of code to be tested for errors while it is being executed. The catch statement allows you to define a block of code to be executed, if an error occurs in the try block.

How do you use a try block variable in catch block?

Variables in try block So, if you declare a variable in try block, (for that matter in any block) it will be local to that particular block, the life time of the variable expires after the execution of the block. Therefore, you cannot access any variable declared in a block, outside it.


2 Answers

Whenever I run across something like this, I use a function:

function constTryCatch(valueFn, catchFn) {
  try {
    return valueFn();
  } catch (e) {
    if (catchFn) catchFn(e);
    return null;
  }
}

const obj = { foo: 'bar' };
const x = constTryCatch(() => obj.foo);
console.log(x);
const y = constTryCatch(() => obj.foo.bar.baz, (e) => console.log(e));
console.log(y);
// example, if the rest of the block depends on `y` being truthy:
// if (!y) return;

Note, the stack snippet doesn't display the error properly. In the real browser console, you'll see something like this:

bar

TypeError: Cannot read property 'baz' of undefined at constTryCatch ((index):79) at constTryCatch ((index):69) at window.onload ((index):79)

null

like image 74
CertainPerformance Avatar answered Oct 25 '22 22:10

CertainPerformance


Go functional - use a helper function with three callbacks:

function Try(attempt, onSuccess, onFailure) {
  try {
    var res = attempt();
  } catch(err) {
    return onFailure(err);
  }
  return onSuccess(res);
}

This allows you to write

return Try(() => …, x => {
  // rest of the code that uses `x`
  const y = x + …;
}, e => void e);

You can also make use of a data structure representing this control flow, like the Result monad (also known as the Either monad):

class Result {
  constructor(go) {
    this.go = go;
  }
  static Ok(v) {
    return new this((onSuccess, _) => onSuccess(v));
  }
  static Err(r) {
    return new this((_, onFailure) => onFailure(v));
  }
  map(f) {
    return this.go(v => Result.Ok(f(v)), r => Result.Err(r));
  }
  chain(f) {
    return this.go(v => f(v), r => Result.Err(r));
  }
  unwrap() {
    return this.go(v => v, r => { throw r; });
  }
}
function Try(attempt) {
  try {
    var res = attempt();
    return Result.Ok(res);
  } catch(e) {
    return Result.Err(e);
  }
}

You could use it very similar to the above simple helper function:

return Try(() =>
  … // exceptions in here are caught
).go(x => {
  // rest of the code that uses `x` - exceptions are not caught
  const y = x + …;
}, e => void e);

But also with more advanced chaining:

return Try(() =>
  … // exceptions in here are caught
).chain(x =>
  Try(() =>
    x + … // exceptions in here are caught as well
  )
).map(y =>
  … // exceptions in here are not caught
).unwrap(); // any caught exceptions are re-thrown
like image 26
Bergi Avatar answered Oct 26 '22 00:10

Bergi