Skip to content

Throwing errors in async await functions and catching from where it’s called

How can we catch error from an async await function from where it’s called?

For example, I have a React component which calls a async-await function imported from another module. When I use Promise.reject("An unknown has occurred"); in that function, so in my React component why can’t I get the error in asyncAwaitFunction.catch((e)=>console.log(e))?

I even tried throw "An unknown occured", but it doesn’t seem to work.

react component

const handleSubmit = async (e) => {
    e.preventDefault();
    add(formData, code)
      .then(() => router.push("/dashboard/manage"))
      .catch((e) => setError(e)); //I want error to be catched here
  };

functions.js

export const addUser = async (details, code) => {

 const isExist = await isUser(code);

 if (!isExist) {

  const add = db.batch();    //firebase batch write

  add.set(userID(code), details);    //Add details to databse

  add.commit()
   .catch((e)=> {
   console.log(e);    // error occurs confirmed
   Promise.reject("Unknown error occurred"); //this does't get catched in component.
  });
    
 } else {
   Promise.reject("Already Exists!"); 
 }
};

Answer

A rejected Promise (either from a Promise that you constructed that rejected, or from a Promise.reject) will only be caught if:

  • a .catch is added onto the end of that Promise expression, or
  • that Promise expression is returned inside an async function or a .then, and the caller of the async function or after the .then callback, there’s a .catch

So, you should change to something like:

export const addUser = async (details, code) => {
   const isExist = await isUser(code);
   if (isExist) {
      return Promise.reject('Already Exists!');
   }

   const add = db.batch();    //firebase batch write
   add.set(userID(code), details);    //Add details to databse
   return add.commit().catch((e) => {
      console.log(e);    // error occurs confirmed
      return Promise.reject("Unknown error occurred");
   });
};

But do you really need to log in the .commit().catch? If not, it’d be cleaner to just return the commit Promise and catch in the caller:

export const addUser = async (details, code) => {
   const isExist = await isUser(code);
   if (isExist) {
      return Promise.reject('Already Exists!');
   }

   const add = db.batch();    //firebase batch write
   add.set(userID(code), details);    //Add details to databse
   return add.commit();
};

A Promise that is awaited or returned from an async function will have its errors (or its resolve value) percolate up to the caller of the async function.