-1

Say we have functions A and B that return promises. B should be called only in case A rejects, and I need to log both success and error results of both promises. First, I came up with this piece of code:

const A = () => Promise.reject(true);
const B = () => Promise.resolve(true);

A()
  .then(() => {
    console.log('A success');
  })
  .catch(() => {
    console.log('A error');
    return B();
  })
  .then(() => {
    console.log('B success');
  })
  .catch(() => {
    console.log('B error');
  });

It works fine in case A rejects. In case A resolves, however, I'm getting one additional B success message, which is perfectly expected but which I do not need in this case.

One possible solution I came up with is attaching the .then() for B() right next to the B() call.

const A = () => Promise.reject(true);
const B = () => Promise.resolve(true);

A()
  .then(() => {
    console.log('A success');
  })
  .catch(() => {
    console.log('A error');

    return B().then(() => {
      console.log('B success');
    });
  })
  .catch(() => {
    console.log('B error');
  });

This of course solves my problem but it feels like more of a hack than a solution. I believe there are better approaches and practices for composing this kind of promise chains.

Amir
  • 1
  • 2
    Your second approach looks perfectly fine to me. If you want it to look cleaner you could switch some of the `.then`s with `await`s. If the chain becomes more complicated, you can extract into functions, eg `handleAError` – CertainPerformance Jul 10 '22 at 09:33
  • 3
    Not a hack, that's basically how you do it if you use explicit promise callbacks. (Side note: You mean "if A is fulfilled," not "if A resolves" when contrasting with A rejecting. I write about promise terminology here: https://thenewtoys.dev/blog/2021/02/08/lets-talk-about-how-to-talk-about-promises/) – T.J. Crowder Jul 10 '22 at 09:34

1 Answers1

1

This is quite fine. However, notice that your catch handlers also run if any of the previous then handlers did cause an error, not only if A() or B() errored. I therefore recommend using .then(…, …) instead of .then(…).catch(…):

A().then(() => {
  console.log('A success');
}, e => {
  console.log('A error', e);
  return B().then(() => {
    console.log('B success');
  }, e => {
    console.log('B error', e);
  });
});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375