0

I have the following function:

async myFunction() {
    await this.somePromiseFunction().then(
      () => alert('Promise Complete!'),
      () => {
        throw new Error('Error');
      }
    ).catch(() => {
      alert('End the Function Here');
      });

    alert('Do not get called if error caught above.');
    await this.anotherPromiseFunction().then(
      () => alert('Promise Complete!'),
      () => {
        throw new Error('Error');
      }
    ).catch(() => {
      alert('End the Function Here');
      });
}

I would like it such that when an error is caught in the promise return handler that it ends the asynchronous function as I do not want it to continue in that case.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
TheGreatZab
  • 163
  • 1
  • 3
  • 18
  • Why don't you put the alert inside the try block.That way if an error occurs the alert won't execute – Manos Kounelakis Nov 21 '19 at 17:27
  • I have multiple promises in my real function, this would mean I would have nest each of them in the previous try block, I want them to stay separated. – TheGreatZab Nov 21 '19 at 17:28
  • Maybe post your full code so we can see if it can be refactored and if we can fix your problem – Manos Kounelakis Nov 21 '19 at 17:29
  • Added other promise function, essentially, I will have many of these in a row and would most definitely want to avoid nesting them within each other. – TheGreatZab Nov 21 '19 at 17:35

1 Answers1

1

Instead of mixing await with .then(), just await each asynchronous function call directly in a try block and deal with the error appropriately.

If the asynchronous function returns a rejected promise, await will cause the rejection to throw from the try block and be caught, skipping the rest of the control flow inside the try.

const asyncFactory = label => async () => {
  await new Promise(resolve => { setTimeout(resolve, 1000); });

  if (Math.random() < 0.25) {
    throw new Error(`${label} Error`);
  }

  console.log(`${label} Complete!`);
};

const somePromiseFunction = asyncFactory('somePromiseFunction');
const anotherPromiseFunction = asyncFactory('anotherPromiseFunction');

async function myFunction() {
  try {
    console.log('Start myFunction here');
    await somePromiseFunction();
    await anotherPromiseFunction();
  } catch (error) {
    console.log('Error caught:', error.message);
  } finally {
    console.log('End myFunction here');
  }
}

myFunction();

You can actually achieve the equivalent without using async and await, and you don't need to nest your promises to do so:

const asyncFactory = label => () => {
  return new Promise(resolve => {
    setTimeout(resolve, 1000);
  }).then(() => {
    if (Math.random() < 0.25) {
      throw new Error(`${label} Error`);
    }

    console.log(`${label} Complete!`);
  });
};

const somePromiseFunction = asyncFactory('somePromiseFunction');
const anotherPromiseFunction = asyncFactory('anotherPromiseFunction');
const oneMorePromiseFunction = asyncFactory('oneMorePromiseFunction');

function myFunction() {
  console.log('Start myFunction here');

  return somePromiseFunction().then(() => {
    return anotherPromiseFunction();
  }).then(() => {
    return oneMorePromiseFunction();
  }).catch(error => {
    console.log('Error caught:', error.message);
  }).finally(() => {
    console.log('End myFunction here');
  });
}

myFunction();

Do note that Promise.prototype.finally() is actually part of ECMAScript 2018, so if the browser supports it natively, it will also already support async and await. However, it can be polyfilled while async and await cannot.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153