After years writing promises, today I learned that we can pass a callback to be called "on rejection" as a second parameter to the .then() method:
const myPromise = () =>
  new Promise((resolve, reject) => {
    reject('something went wrong');
  });
myPromise()
  .then(console.log, (error) => {
    console.log('inside the then error callback', error);
  });This can be useful when we want to chain multiple "then" and do something if it fails I can add a very specific handler that intercepts this error, do something and either allow to continue the flow (it goes to the next .then() on success) or re-throw:
const myPromise = () =>
  new Promise((resolve, reject) => {
    reject('Something went wrong');
  });
const firstThenHandlers = {
  onSuccess(){
    console.log('First then: success');
  },
  onError(err){
    console.log('First then: error', err);
  }
}
const secondThenHandlers = {
  onSuccess(){
    console.log('Second then: success');
  },
  onError(err){
    console.log('Second then: error', err);
  }
}
myPromise()
  .then(firstThenHandlers.onSuccess, firstThenHandlers.onError)
  //becase I'm not re-throwing the error, the error won't reach `.catch` method
  .then(secondThenHandlers.onSuccess, secondThenHandlers.onError)
  .catch((error) => {    // never reached
    console.log('Catch callback: ', error);
  });The curious fact is that since I'm intercepting the error with this callback, whatever I return from the firstThenHandlers.onError, will be passed to secondThenHandlers.onSuccess, which can be the error itself or a fallback response.
The possibilities are many. I think it worth a blog post in the future about this.