Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throw custom errors async/await try-catch

Let's say I have a function like this -

doSomeOperation = async () => {
  try {
    let result = await DoSomething.mightCauseException();
    if (result.invalidState) {
      throw new Error("Invalid State error");
    }

    return result;
  } catch (error) {
    ExceptionLogger.log(error);
    throw new Error("Error performing operation");
  }
};

Here the DoSomething.mightCauseException is an asynchronous call that might cause an exception and I'm using try..catch to handle it. But then using the result obtained, I might decide that I need to tell the caller of doSomeOperation that the operation has failed with a certain reason.

In the above function, the Error I'm throwing is caught by the catch block and only a generic Error gets thrown back to the caller of doSomeOperation.

Caller of doSomeOperation might be doing something like this -

doSomeOperation()
  .then((result) => console.log("Success"))
  .catch((error) => console.log("Failed", error.message))

My custom error never gets here.

This pattern can be used when building Express apps. The route handler would call some function which might want to fail in different ways and let the client know why it failed.

I'm wondering how this can be done? Is there any other pattern to follow here? Thanks!

like image 351
Steve Robinson Avatar asked Apr 18 '26 20:04

Steve Robinson


1 Answers

Just change the order of your lines.

doSomeOperation = async() => {
    let result = false;
    try {
        result = await DoSomething.mightCauseException();
    } catch (error) {
        ExceptionLogger.log(error);
        throw new Error("Error performing operation");
    }
    if (!result || result.invalidState) {
        throw new Error("Invalid State error");
    }
    return result;
};

Update 1

Or you could create custom errors as below.

class MyError extends Error {
  constructor(m) {
    super(m);
  }
}

function x() {
  try {
    throw new MyError("Wasted");
  } catch (err) {
    if (err instanceof MyError) {
      throw err;
    } else {
      throw new Error("Bummer");
    }
  }

}

x();

Update 2

Mapping this to your case,

class MyError extends Error {
  constructor(m) {
    super(m);
  }
}

doSomeOperation = async() => {
  try {
    let result = await mightCauseException();
    if (result.invalidState) {
      throw new MyError("Invalid State error");
    }

    return result;
  } catch (error) {
    if (error instanceof MyError) {
      throw error;
    }
    throw new Error("Error performing operation");
  }
};

async function mightCauseException() {
  let random = Math.floor(Math.random() * 1000);
  if (random % 3 === 0) {
    return {
      invalidState: true
    }
  } else if (random % 3 === 1) {
    return {
      invalidState: false
    }
  } else {
    throw Error("Error from function");
  }
}


doSomeOperation()
  .then((result) => console.log("Success"))
  .catch((error) => console.log("Failed", error.message))
like image 136
Chathura Widanage Avatar answered Apr 21 '26 22:04

Chathura Widanage



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!